processed in order by display_bfd(). If the file is an archive each
of its elements is processed in turn.
- 3. The file's target architecture and binary file format are determnined
+ 3. The file's target architecture and binary file format are determined
by bfd_check_format(). If they are recognised, then dump_bfd() is
called.
- 4. dump_bfd() in turn calls seperate functions to display the requested
- item(s) of infomation(s). For example dissasemble_data() is called if
- a disassmebly has been requested.
+ 4. dump_bfd() in turn calls separate functions to display the requested
+ item(s) of information(s). For example disassemble_data() is called if
+ a disassembly has been requested.
When disassembling the code loops through blocks of instructions bounded
- by symbols, calling dissassemble_bytes() on each block. The actual
+ by symbols, calling disassemble_bytes() on each block. The actual
disassembling is done by the libopcodes library, via a function pointer
supplied by the disassembler() function. */
static char *default_target = NULL; /* Default at runtime. */
-/* The following variables are set based on arguments passed on command line. */
+/* The following variables are set based on arguments passed on the
+ command line. */
static int show_version = 0; /* Show the version number. */
static int dump_section_contents; /* -s */
static int dump_section_headers; /* -h */
static const char **include_paths;
static int include_path_count;
-/* Extra info to pass to the section disassembler and address printing function. */
+/* Extra info to pass to the section disassembler and address printing
+ function. */
struct objdump_disasm_info
{
bfd * abfd;
{
char buf[30];
char *p;
- struct objdump_disasm_info *aux
- = (struct objdump_disasm_info *) info->application_data;
+ struct objdump_disasm_info *aux;
+ aux = (struct objdump_disasm_info *) info->application_data;
bfd_sprintf_vma (aux->abfd, buf, vma);
if (! skip_zeroes)
p = buf;
free (alloc);
}
-/* Locate a symbol given a bfd, a section, and a VMA. If REQUIRE_SEC
- is TRUE, then always require the symbol to be in the section. This
- returns NULL if there is no suitable symbol. If PLACE is not NULL,
- then *PLACE is set to the index of the symbol in sorted_syms. */
+/* Locate a symbol given a bfd and a section (from INFO->application_data),
+ and a VMA. If INFO->application_data->require_sec is TRUE, then always
+ require the symbol to be in the section. Returns NULL if there is no
+ suitable symbol. If PLACE is not NULL, then *PLACE is set to the index
+ of the symbol in sorted_syms. */
static asymbol *
-find_symbol_for_address (bfd *abfd, asection *sec, bfd_vma vma,
- bfd_boolean require_sec, long *place)
+find_symbol_for_address (bfd_vma vma,
+ struct disassemble_info *info,
+ long *place)
{
/* @@ Would it speed things up to cache the last two symbols returned,
and maybe their address ranges? For many processors, only one memory
long min = 0;
long max = sorted_symcount;
long thisplace;
- unsigned int opb = bfd_octets_per_byte (abfd);
+ struct objdump_disasm_info *aux;
+ bfd *abfd;
+ asection *sec;
+ unsigned int opb;
if (sorted_symcount < 1)
return NULL;
+ aux = (struct objdump_disasm_info *) info->application_data;
+ abfd = aux->abfd;
+ sec = aux->sec;
+ opb = bfd_octets_per_byte (abfd);
+
/* Perform a binary search looking for the closest symbol to the
required value. We are searching the range (min, max]. */
while (min + 1 < max)
no way to tell what's desired without looking at the relocation
table. */
if (sorted_syms[thisplace]->section != sec
- && (require_sec
+ && (aux->require_sec
|| ((abfd->flags & HAS_RELOC) != 0
&& vma >= bfd_get_section_vma (abfd, sec)
&& vma < (bfd_get_section_vma (abfd, sec)
}
if (sorted_syms[thisplace]->section != sec
- && (require_sec
+ && (aux->require_sec
|| ((abfd->flags & HAS_RELOC) != 0
&& vma >= bfd_get_section_vma (abfd, sec)
&& vma < (bfd_get_section_vma (abfd, sec)
+ bfd_section_size (abfd, sec)))))
- {
- /* There is no suitable symbol. */
- return NULL;
- }
+ /* There is no suitable symbol. */
+ return NULL;
+ }
+
+ /* Give the target a chance to reject the symbol. */
+ while (! info->symbol_is_valid (sorted_syms [thisplace], info))
+ {
+ ++ thisplace;
+ if (thisplace >= sorted_symcount
+ || bfd_asymbol_value (sorted_syms [thisplace]) > vma)
+ return NULL;
}
if (place != NULL)
If SKIP_ZEROES is TRUE, don't output leading zeroes. */
static void
-objdump_print_addr (bfd_vma vma, struct disassemble_info *info,
+objdump_print_addr (bfd_vma vma,
+ struct disassemble_info *info,
bfd_boolean skip_zeroes)
{
struct objdump_disasm_info *aux;
}
aux = (struct objdump_disasm_info *) info->application_data;
- sym = find_symbol_for_address (aux->abfd, aux->sec, vma, aux->require_sec,
- NULL);
+ sym = find_symbol_for_address (vma, info, NULL);
objdump_print_addr_with_sym (aux->abfd, aux->sec, sym, vma, info,
skip_zeroes);
}
static int
objdump_symbol_at_address (bfd_vma vma, struct disassemble_info * info)
{
- struct objdump_disasm_info * aux;
asymbol * sym;
- /* No symbols - do not bother checking. */
- if (sorted_symcount < 1)
- return 0;
-
- aux = (struct objdump_disasm_info *) info->application_data;
- sym = find_symbol_for_address (aux->abfd, aux->sec, vma, aux->require_sec,
- NULL);
+ sym = find_symbol_for_address (vma, info, NULL);
return (sym != NULL && (bfd_asymbol_value (sym) == vma));
}
static unsigned int prev_line;
/* We keep a list of all files that we have seen when doing a
- dissassembly with source, so that we know how much of the file to
+ disassembly with source, so that we know how much of the file to
display. This can be important for inlined functions. */
struct print_file_list
}
}
-/* Show the line number, or the source line, in a dissassembly
+/* Show the line number, or the source line, in a disassembly
listing. */
static void
typedef struct
{
char *buffer;
- size_t size;
- char *current;
+ size_t pos;
+ size_t alloc;
} SFILE;
/* sprintf to a "stream". */
static int
objdump_sprintf (SFILE *f, const char *format, ...)
{
- char *buf;
size_t n;
va_list args;
- va_start (args, format);
-
- vasprintf (&buf, format, args);
-
- if (buf == NULL)
+ while (1)
{
+ size_t space = f->alloc - f->pos;
+
+ va_start (args, format);
+ n = vsnprintf (f->buffer + f->pos, space, format, args);
va_end (args);
- fatal (_("Out of virtual memory"));
- }
-
- n = strlen (buf);
-
- while ((size_t) ((f->buffer + f->size) - f->current) < n + 1)
- {
- size_t curroff;
- curroff = f->current - f->buffer;
- f->size *= 2;
- f->buffer = xrealloc (f->buffer, f->size);
- f->current = f->buffer + curroff;
+ if (space > n)
+ break;
+
+ f->alloc = (f->alloc + n) * 2;
+ f->buffer = xrealloc (f->buffer, f->alloc);
}
-
- memcpy (f->current, buf, n);
- f->current += n;
- f->current[0] = '\0';
-
- free (buf);
-
- va_end (args);
+ f->pos += n;
+
return n;
}
int skip_addr_chars;
bfd_vma addr_offset;
int opb = info->octets_per_byte;
+ SFILE sfile;
aux = (struct objdump_disasm_info *) info->application_data;
section = aux->sec;
+ sfile.alloc = 120;
+ sfile.buffer = xmalloc (sfile.alloc);
+ sfile.pos = 0;
+
if (insns)
octets_per_line = 4;
else
else
{
char buf[50];
- SFILE sfile;
int bpc = 0;
int pb = 0;
if (insns)
{
- sfile.size = 120;
- sfile.buffer = xmalloc (sfile.size);
- sfile.current = sfile.buffer;
+ sfile.pos = 0;
info->fprintf_func = (fprintf_ftype) objdump_sprintf;
info->stream = (FILE *) &sfile;
info->bytes_per_line = 0;
octets_per_line = info->bytes_per_line;
if (octets < 0)
{
- if (sfile.current != sfile.buffer)
+ if (sfile.pos)
printf ("%s\n", sfile.buffer);
- free (sfile.buffer);
break;
}
}
if (! insns)
printf ("%s", buf);
- else
- {
- printf ("%s", sfile.buffer);
- free (sfile.buffer);
- }
+ else if (sfile.pos)
+ printf ("%s", sfile.buffer);
if (prefix_addresses
? show_raw_insn > 0
else
printf ("\t\t\t");
- objdump_print_value (section->vma + q->address, info, TRUE);
+ objdump_print_value (section->vma - rel_offset + q->address,
+ info, TRUE);
printf (": %s\t", q->howto->name);
addr_offset += octets / opb;
}
+
+ free (sfile.buffer);
}
static void
disassemble_section (bfd *abfd, asection *section, void *info)
{
struct disassemble_info * pinfo = (struct disassemble_info *) info;
- struct objdump_disasm_info * paux = (struct objdump_disasm_info *) pinfo->application_data;
+ struct objdump_disasm_info * paux;
unsigned int opb = pinfo->octets_per_byte;
bfd_byte * data = NULL;
bfd_size_type datasize = 0;
return;
/* Decide which set of relocs to use. Load them if necessary. */
+ paux = (struct objdump_disasm_info *) pinfo->application_data;
if (paux->dynrelbuf)
{
rel_pp = paux->dynrelbuf;
rel_count = paux->dynrelcount;
/* Dynamic reloc addresses are absolute, non-dynamic are section
- relative. REL_OFFSET specifies the reloc address corresponnding
+ relative. REL_OFFSET specifies the reloc address corresponding
to the start of this section. */
- rel_offset = pinfo->buffer_vma;
+ rel_offset = section->vma;
}
else
{
printf (_("Disassembly of section %s:\n"), section->name);
/* Find the nearest symbol forwards from our current position. */
- sym = find_symbol_for_address (abfd, section, section->vma + addr_offset,
- TRUE, &place);
+ paux->require_sec = TRUE;
+ sym = find_symbol_for_address (section->vma + addr_offset, info, &place);
+ paux->require_sec = FALSE;
/* Disassemble a block of instructions up to the address associated with
the symbol we have just found. Then print the symbol and find the
or we have reached the end of the address range we are interested in. */
while (addr_offset < stop_offset)
{
+ bfd_vma addr;
asymbol *nextsym;
unsigned long nextstop_offset;
bfd_boolean insns;
- if (sym != NULL
- && bfd_asymbol_value (sym) <= section->vma + addr_offset)
+ addr = section->vma + addr_offset;
+
+ if (sym != NULL && bfd_asymbol_value (sym) <= addr)
{
int x;
for (x = place;
(x < sorted_symcount
- && (bfd_asymbol_value (sorted_syms[x])
- <= section->vma + addr_offset));
+ && (bfd_asymbol_value (sorted_syms[x]) <= addr));
++x)
continue;
- pinfo->symbols = & sorted_syms[place];
+ pinfo->symbols = sorted_syms + place;
pinfo->num_symbols = x - place;
}
else
- pinfo->symbols = NULL;
+ {
+ pinfo->symbols = NULL;
+ pinfo->num_symbols = 0;
+ }
if (! prefix_addresses)
{
pinfo->fprintf_func (pinfo->stream, "\n");
- objdump_print_addr_with_sym (abfd, section, sym,
- section->vma + addr_offset,
+ objdump_print_addr_with_sym (abfd, section, sym, addr,
pinfo, FALSE);
pinfo->fprintf_func (pinfo->stream, ":\n");
}
- if (sym != NULL
- && bfd_asymbol_value (sym) > section->vma + addr_offset)
+ if (sym != NULL && bfd_asymbol_value (sym) > addr)
nextsym = sym;
else if (sym == NULL)
nextsym = NULL;
else
{
+#define is_valid_next_sym(SYM) \
+ ((SYM)->section == section \
+ && (bfd_asymbol_value (SYM) > bfd_asymbol_value (sym)) \
+ && pinfo->symbol_is_valid (SYM, pinfo))
+
/* Search forward for the next appropriate symbol in
SECTION. Note that all the symbols are sorted
together into one big array, and that some sections
may have overlapping addresses. */
while (place < sorted_symcount
- && (sorted_syms[place]->section != section
- || (bfd_asymbol_value (sorted_syms[place])
- <= bfd_asymbol_value (sym))))
+ && ! is_valid_next_sym (sorted_syms [place]))
++place;
+
if (place >= sorted_symcount)
nextsym = NULL;
else
nextsym = sorted_syms[place];
}
- if (sym != NULL
- && bfd_asymbol_value (sym) > section->vma + addr_offset)
- {
- nextstop_offset = bfd_asymbol_value (sym) - section->vma;
- if (nextstop_offset > stop_offset)
- nextstop_offset = stop_offset;
- }
+ if (sym != NULL && bfd_asymbol_value (sym) > addr)
+ nextstop_offset = bfd_asymbol_value (sym) - section->vma;
else if (nextsym == NULL)
nextstop_offset = stop_offset;
else
- {
- nextstop_offset = bfd_asymbol_value (nextsym) - section->vma;
- if (nextstop_offset > stop_offset)
- nextstop_offset = stop_offset;
- }
+ nextstop_offset = bfd_asymbol_value (nextsym) - section->vma;
+
+ if (nextstop_offset > stop_offset)
+ nextstop_offset = stop_offset;
/* If a symbol is explicitly marked as being an object
rather than a function, just dump the bytes without
disassembling them. */
if (disassemble_all
|| sym == NULL
- || bfd_asymbol_value (sym) > section->vma + addr_offset
+ || bfd_asymbol_value (sym) > addr
|| ((sym->flags & BSF_OBJECT) == 0
&& (strstr (bfd_asymbol_name (sym), "gnu_compiled")
== NULL)
/* Sort the symbols into section and symbol order. */
qsort (sorted_syms, sorted_symcount, sizeof (asymbol *), compare_symbols);
- init_disassemble_info (&disasm_info, stdout, fprintf);
+ init_disassemble_info (&disasm_info, stdout, (fprintf_ftype) fprintf);
disasm_info.application_data = (void *) &aux;
aux.abfd = abfd;
instead. */
disasm_info.endian = BFD_ENDIAN_UNKNOWN;
+ /* Allow the target to customize the info structure. */
+ disassemble_init_for_target (& disasm_info);
+
/* Pre-load the dynamic relocs if we are going
to be dumping them along with the disassembly. */
if (dump_dynamic_reloc_info)
if (relsize > 0)
{
aux.dynrelbuf = xmalloc (relsize);
- aux.dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, aux.dynrelbuf, dynsyms);
+ aux.dynrelcount = bfd_canonicalize_dynamic_reloc (abfd,
+ aux.dynrelbuf,
+ dynsyms);
if (aux.dynrelcount < 0)
bfd_fatal (bfd_get_filename (abfd));
/* Sort the relocs by address. */
- qsort (aux.dynrelbuf, aux.dynrelcount, sizeof (arelent *), compare_relocs);
+ qsort (aux.dynrelbuf, aux.dynrelcount, sizeof (arelent *),
+ compare_relocs);
}
}
using string table section STRSECT_NAME (in `strtab'). */
static void
-print_section_stabs (bfd *abfd, const char *stabsect_name, unsigned *string_offset_ptr)
+print_section_stabs (bfd *abfd,
+ const char *stabsect_name,
+ unsigned *string_offset_ptr)
{
int i;
unsigned file_string_table_offset = 0;
}
static void
-dump_relocs_in_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED)
+dump_relocs_in_section (bfd *abfd,
+ asection *section,
+ void *dummy ATTRIBUTE_UNUSED)
{
arelent **relpp;
long relcount;
}
static void
-adjust_addresses (bfd *abfd ATTRIBUTE_UNUSED, asection *section, void *dummy ATTRIBUTE_UNUSED)
+adjust_addresses (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *section,
+ void *dummy ATTRIBUTE_UNUSED)
{
section->vma += adjust_section_vma;
section->lma += adjust_section_vma;
static void
display_file (char *filename, char *target)
{
- bfd *file, *arfile = NULL;
+ bfd *file;
+ bfd *arfile = NULL;
+
+ if (get_file_size (filename) < 1)
+ return;
file = bfd_openr (filename, target);
if (file == NULL)