create one debug hunk for loadables and make objdump work again

This commit is contained in:
bebbo 2018-02-07 23:14:14 +01:00
parent f494ffb0f9
commit eb800e9744
3 changed files with 273 additions and 40 deletions

View File

@ -126,6 +126,18 @@
#define BYTES_IN_WORD 4
#include "aout/aout64.h" /* struct external_nlist */
#ifndef PARAMS
#define PARAMS(x) x
#endif
typedef struct aout_symbol {
asymbol symbol;
short desc;
char other;
unsigned char type;
} aout_symbol_type;
#ifndef alloca
extern PTR alloca PARAMS ((size_t));
#endif
@ -162,6 +174,19 @@ typedef struct amiga_ardata_struct {
/* AmigaOS doesn't like HUNK_SYMBOL with symbol names longer than 124 characters */
#define MAX_NAME_SIZE 124
aout_symbol_type **
amiga_load_stab_symbols (bfd *abfd);
bfd_boolean
aout_32_find_nearest_line (bfd *abfd, sec_ptr section, struct aout_symbol **symbols,
bfd_vma offset, const char **filename_ptr, const char **functionname_ptr,
unsigned int *line_ptr);
bfd_boolean
aout_32_translate_symbol_table (bfd *abfd, aout_symbol_type *in, struct external_nlist *ext,
bfd_size_type count, char *str, bfd_size_type strsize, bfd_boolean dynamic);
static bfd_boolean amiga_reloc_long_p PARAMS ((unsigned long, bfd_boolean));
static reloc_howto_type *howto_for_raw_reloc PARAMS ((unsigned long, bfd_boolean));
static reloc_howto_type *howto_for_reloc PARAMS ((unsigned long));
@ -1061,6 +1086,16 @@ amiga_read_load (
}/* Of switch */
}
/* read stab */
if (get_long (abfd, &hunk_type) && hunk_type == HUNK_DEBUG)
{
unsigned long sz;
get_long (abfd, &sz) &&
bfd_seek(abfd, -4, SEEK_CUR) >= 0 &&
amiga_handle_cdb_hunk (abfd, hunk_type, -1, 0, sz);
}
return TRUE;
}/* Of amiga_read_load */
@ -1574,7 +1609,7 @@ amiga_write_object_contents (
{
long datadata_relocs = 0, bss_size = 0, idx;
int *index_map, max_hunk = -1;
sec_ptr data_sec, p, q;
sec_ptr data_sec, p, q, stab = 0, stabstr = 0;
unsigned long i, n[5];
/* Distinguish UNITS, LOAD Files
@ -1585,52 +1620,46 @@ amiga_write_object_contents (
if (AMIGA_DATA(abfd)->IsLoadFile)
{
// shuffle .stab and .stabstr to end
for (q = abfd->sections, p = q->next; p != NULL; q = p, p = p->next)
// remove .stab and .stabstr
for (q = abfd->sections, p = q->next; ; p = p->next)
{
if (0 == strcmp (p->name, ".stab"))
{
if (p->next)
{
q->next = p->next;
if (write_debug_hunk)
{
q = p->next;
while (q->next)
q = q->next;
q->next = p;
p->next = 0;
}
}
else
q->next = 0;
break;
stab = p;
q->next = p->next;
if (!p->next)
break;
continue;
}
}
for (q = abfd->sections, p = q->next; p != NULL; q = p, p = p->next)
{
if (0 == strcmp (p->name, ".stabstr"))
{
if (p->next)
{
q->next = p->next;
if (write_debug_hunk)
{
q = p->next;
while (q->next)
q = q->next;
q->next = p;
p->next = 0;
}
}
else
q->next = 0;
break;
stabstr = p;
q->next = p->next;
if (!p->next)
break;
continue;
}
q = p;
}
// q points to last section - patch stab section and append
if (write_debug_hunk && stab && stabstr)
{
unsigned total = 12 + stab->_raw_size + stabstr->_raw_size;
unsigned char * data = (unsigned char *)bfd_alloc(abfd, total);
bfd_putb32(ZMAGIC, data);
bfd_putb32(stab->_raw_size, data + 4);
bfd_putb32(stabstr->_raw_size, data + 8);
memcpy(data + 12, stab->contents, stab->_raw_size);
memcpy(data + 12 + stab->_raw_size, stabstr->contents, stabstr->_raw_size);
stab->_raw_size = stab->_cooked_size = total;
stab->contents = data;
q->next = stab;
stab->next = 0;
}
int n = 0;
for (p = abfd->sections; p != NULL; p = p->next)
p->index = n++;
abfd->section_count = n;
}
index_map = bfd_alloc (abfd, abfd->section_count * sizeof(int));
@ -1659,7 +1688,7 @@ amiga_write_object_contents (
&& !(amiga_base_relative && !strcmp (p->name, ".bss")))
{
/* don't count debug sections. */
if (strcmp (p->name, ".stab") && strcmp (p->name, ".stabstr"))
if (strcmp (p->name, ".stab"))
n[2]++;
}
else
@ -2845,6 +2874,8 @@ amiga_slurp_symbol_table (
if (bfd_bread (stabstrdata, astabstr->disk_size, abfd) != astabstr->disk_size)
return FALSE;
stabstr->contents = stabstrdata;
unsigned char * stabdata = (unsigned char *) bfd_alloc (abfd, astab->disk_size);
if (!stabdata)
return FALSE;
@ -2853,6 +2884,8 @@ amiga_slurp_symbol_table (
if (bfd_bread (stabdata, astab->disk_size, abfd) != astab->disk_size)
return FALSE;
stab->contents = stabdata;
{unsigned i; for (i = 0; i < astab->disk_size; i += 12)
{
unsigned str_offset = bfd_getb32 (stabdata + i);
@ -3299,6 +3332,77 @@ amiga_sizeof_headers (
return 0;
}
/*
* Load the stab symbols if both sections .stab and .stabstr exist.
* For Loadables use the stabs DEBUG section, if present
*/
aout_symbol_type **
amiga_load_stab_symbols (bfd *abfd)
{
amiga_data_type *amiga_data = AMIGA_DATA(abfd);
if (amiga_data->stab_symbols)
return amiga_data->stab_symbols;
/* search the stab sections. */
unsigned char * stab = 0;
unsigned char * stabstr = 0;
sec_ptr s;
for (s = abfd->sections; s; s = s->next)
{
if (0 == strcmp(".text", s->name))
amiga_data->a.textsec = s;
else
if (0 == strcmp(".data", s->name))
amiga_data->a.datasec = s;
else
if (0 == strcmp(".bss", s->name))
amiga_data->a.bsssec = s;
else
if (0 == strcmp(".stab", s->name))
{
amiga_data->symtab_size = s->_raw_size;
stab = s->contents;
}
else
if (0 == strcmp(".stabstr", s->name))
{
amiga_data->stringtab_size = s->_raw_size;
stabstr = s->contents;
}
}
if (!stab || !stabstr)
{
if (!adata(abfd).sym_filepos || !adata(abfd).str_filepos)
return 0;
// executable - load the data now.
stab = (unsigned char *)bfd_alloc(abfd, amiga_data->symtab_size);
bfd_seek(abfd, adata(abfd).sym_filepos, SEEK_SET);
if (bfd_bread (stab, amiga_data->symtab_size, abfd) != amiga_data->symtab_size)
return 0;
stabstr = (unsigned char *)bfd_alloc(abfd, amiga_data->stringtab_size);
bfd_seek(abfd, adata(abfd).str_filepos, SEEK_SET);
if (bfd_bread (stabstr, amiga_data->stringtab_size, abfd) != amiga_data->stringtab_size)
return 0;
}
unsigned num = amiga_data->symtab_size / sizeof(struct external_nlist);
struct aout_symbol * asyms = (struct aout_symbol *)bfd_zalloc(abfd, num * sizeof(struct aout_symbol));
if (!aout_32_translate_symbol_table(abfd, asyms, (struct external_nlist *) stab, num, (char *)stabstr, amiga_data->stringtab_size, 0))
return 0;
struct aout_symbol ** ss = (struct aout_symbol **)bfd_alloc(abfd, (1 + num) * sizeof(struct aout_symbol *));
unsigned i;
for (i = 0; i < num; ++i)
ss[i] = &asyms[i];
ss[num] = 0;
amiga_data->stab_symbols = ss;
return ss;
}
/* Provided a BFD, a section and an offset into the section, calculate
and return the name of the source file and the line nearest to the
wanted location. */
@ -3312,6 +3416,9 @@ amiga_find_nearest_line (
const char **functionname_ptr ATTRIBUTE_UNUSED,
unsigned int *line_ptr ATTRIBUTE_UNUSED)
{
aout_symbol_type **stab_symbols = amiga_load_stab_symbols(abfd);
if (stab_symbols)
return aout_32_find_nearest_line(abfd, section, stab_symbols, offset, filename_ptr, functionname_ptr, line_ptr);
/* FIXME (see aoutx.h, for example) */
return FALSE;
}
@ -3390,7 +3497,7 @@ amiga_slurp_armap (
for (csym = defsyms; syms; syms = syms->next)
{
unsigned long type, len, n;
unsigned long len, n;
char *symblock;
if(csym >= defsyms + symcount)
@ -3419,7 +3526,7 @@ amiga_slurp_armap (
symblock += 4;
len = n & 0xffffff;
type = (n >> 24) & 0xff;
//type = (n >> 24) & 0xff;
len <<= 2;
csym->name = symblock;
csym->name[len] = '\0';

View File

@ -448,6 +448,73 @@ get_relocated_section_contents (
}
}
/*
* update the associated .stab if .stabstr
*/
if (input_section->output_offset && 0 == strcmp(input_section->name, ".stabstr"))
{
sec_ptr s_txt = 0;
sec_ptr s_data = 0;
sec_ptr s_bss = 0;
sec_ptr s = input_bfd->sections;
while (s && s->next != input_section)
{
if (0 == strcmp(s->name, ".text"))
s_txt = s;
else if (0 == strcmp(s->name, ".data"))
s_data = s;
if (0 == strcmp(s->name, ".bss"))
s_bss = s;
s = s->next;
}
if (s) {
unsigned char * start = s->output_section->contents + s->output_offset;
unsigned char * end = start + s->_raw_size;
while (start < end)
{
// update the name
unsigned offset = bfd_getb32(start);
if (offset)
bfd_putb32(offset + input_section->output_offset, start);
offset = bfd_getb32(start + 8);
// update the value
switch (start[4])
{
case 4: //N_TEXT:
case 0x24: // N_FUN:
// already handled via reloc
// case 0x64: //N_SO:
// case 0x44: // N_SLINE:
if (s_txt)
offset += s_txt->output_offset;
break;
case 0x6: // N_DATA:
case 0x26: // N_STSYM:
// already handled via reloc
// case 0x46: // N_DSLINE:
if (s_data)
offset += s_data->output_offset;
break;
case 0x8: // N_BSS:
case 0x28: //N_LCSYM:
// already handled via reloc
// case 0x48: // N_BSLINE:
if (s_bss)
offset += s_bss->output_offset;
break;
default:
break;
}
bfd_putb32(offset, start + 8);
start += 12;
}
}
}
/* We're not relaxing the section, so just copy the size info. */
input_section->_cooked_size = input_section->_raw_size;
input_section->reloc_done = TRUE;

View File

@ -146,12 +146,70 @@ struct amiga_data {
sec_ptr bsssec;
file_ptr sym_filepos;
file_ptr str_filepos;
/* rest intentionally omitted */
/* Size of a relocation entry in external form. */
unsigned reloc_entry_size;
/* Size of a symbol table entry in external form. */
unsigned symbol_entry_size;
/* Page size - needed for alignment of demand paged files. */
unsigned long page_size;
/* Segment size - needed for alignment of demand paged files. */
unsigned long segment_size;
/* Zmagic disk block size - need to align the start of the text
section in ZMAGIC binaries. Normally the same as page_size. */
unsigned long zmagic_disk_block_size;
unsigned exec_bytes_size;
unsigned vma_adjusted : 1;
/* Used when a bfd supports several highly similar formats. */
enum
{
default_format = 0,
/* Used on HP 9000/300 running HP/UX. See hp300hpux.c. */
gnu_encap_format,
/* Used on Linux, 386BSD, etc. See include/aout/aout64.h. */
q_magic_format
} subformat;
enum
{
undecided_magic = 0,
z_magic,
o_magic,
n_magic
} magic;
/* A buffer for find_nearest_line. */
char *line_buf;
/* The external symbol information. */
struct external_nlist *external_syms;
bfd_size_type external_sym_count;
bfd_window sym_window;
char *external_strings;
bfd_size_type external_string_size;
bfd_window string_window;
struct aout_link_hash_entry **sym_hashes;
/* A pointer for shared library information. */
PTR dynamic_info;
/* A mapping from local symbols to offsets into the global offset
table, used when linking on SunOS. This is indexed by the symbol
index. */
bfd_vma *local_got_offsets;
carsym *symdefs; /* the symdef entries */
symindex symdef_count; /* how many there are */
};
struct aout_symbol;
typedef struct amiga_data_struct {
struct amiga_data a;
unsigned long symtab_size;
@ -162,6 +220,7 @@ typedef struct amiga_data_struct {
/* The next two fields are set at final_link time (for the output bfd only) */
bfd_boolean baserel;/* true if there is ___init_a4 in the global hash table */
bfd_vma a4init; /* cache the value for efficiency */
struct aout_symbol ** stab_symbols;
} amiga_data_type;
#define adata(bfd) ((bfd)->tdata.amiga_data->a)