|
|
|
@ -214,6 +214,7 @@ static struct group ** section_headers_groups;
|
|
|
|
|
#define DISASS_DUMP (1 << 1) /* The -i command line switch. */
|
|
|
|
|
#define DEBUG_DUMP (1 << 2) /* The -w command line switch. */
|
|
|
|
|
#define STRING_DUMP (1 << 3) /* The -p command line switch. */
|
|
|
|
|
#define RELOC_DUMP (1 << 4) /* The -R command line switch. */
|
|
|
|
|
|
|
|
|
|
typedef unsigned char dump_type;
|
|
|
|
|
|
|
|
|
@ -2844,11 +2845,12 @@ static struct option options[] =
|
|
|
|
|
{"unwind", no_argument, 0, 'u'},
|
|
|
|
|
{"archive-index", no_argument, 0, 'c'},
|
|
|
|
|
{"hex-dump", required_argument, 0, 'x'},
|
|
|
|
|
{"debug-dump", optional_argument, 0, OPTION_DEBUG_DUMP},
|
|
|
|
|
{"relocated-dump", required_argument, 0, 'R'},
|
|
|
|
|
{"string-dump", required_argument, 0, 'p'},
|
|
|
|
|
#ifdef SUPPORT_DISASSEMBLY
|
|
|
|
|
{"instruction-dump", required_argument, 0, 'i'},
|
|
|
|
|
#endif
|
|
|
|
|
{"debug-dump", optional_argument, 0, OPTION_DEBUG_DUMP},
|
|
|
|
|
|
|
|
|
|
{"version", no_argument, 0, 'v'},
|
|
|
|
|
{"wide", no_argument, 0, 'W'},
|
|
|
|
@ -2885,6 +2887,8 @@ usage (FILE * stream)
|
|
|
|
|
Dump the contents of section <number|name> as bytes\n\
|
|
|
|
|
-p --string-dump=<number|name>\n\
|
|
|
|
|
Dump the contents of section <number|name> as strings\n\
|
|
|
|
|
-R --relocated-dump=<number|name>\n\
|
|
|
|
|
Dump the contents of section <number|name> as relocated bytes\n\
|
|
|
|
|
-w[lLiaprmfFsoR] or\n\
|
|
|
|
|
--debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
|
|
|
|
|
Display the contents of DWARF2 debug sections\n"));
|
|
|
|
@ -2961,6 +2965,22 @@ request_dump_byname (const char * section, dump_type type)
|
|
|
|
|
dump_sects_byname = new_request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
request_dump (dump_type type)
|
|
|
|
|
{
|
|
|
|
|
int section;
|
|
|
|
|
char * cp;
|
|
|
|
|
|
|
|
|
|
do_dump++;
|
|
|
|
|
section = strtoul (optarg, & cp, 0);
|
|
|
|
|
|
|
|
|
|
if (! *cp && section >= 0)
|
|
|
|
|
request_dump_bynumber (section, type);
|
|
|
|
|
else
|
|
|
|
|
request_dump_byname (optarg, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_args (int argc, char ** argv)
|
|
|
|
|
{
|
|
|
|
@ -2970,11 +2990,8 @@ parse_args (int argc, char ** argv)
|
|
|
|
|
usage (stderr);
|
|
|
|
|
|
|
|
|
|
while ((c = getopt_long
|
|
|
|
|
(argc, argv, "ADHINSVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
|
|
|
|
|
(argc, argv, "ADHINR:SVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
|
|
|
|
|
{
|
|
|
|
|
char * cp;
|
|
|
|
|
int section;
|
|
|
|
|
|
|
|
|
|
switch (c)
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
@ -3048,20 +3065,13 @@ parse_args (int argc, char ** argv)
|
|
|
|
|
do_archive_index++;
|
|
|
|
|
break;
|
|
|
|
|
case 'x':
|
|
|
|
|
do_dump++;
|
|
|
|
|
section = strtoul (optarg, & cp, 0);
|
|
|
|
|
if (! *cp && section >= 0)
|
|
|
|
|
request_dump_bynumber (section, HEX_DUMP);
|
|
|
|
|
else
|
|
|
|
|
request_dump_byname (optarg, HEX_DUMP);
|
|
|
|
|
request_dump (HEX_DUMP);
|
|
|
|
|
break;
|
|
|
|
|
case 'p':
|
|
|
|
|
do_dump++;
|
|
|
|
|
section = strtoul (optarg, & cp, 0);
|
|
|
|
|
if (! *cp && section >= 0)
|
|
|
|
|
request_dump_bynumber (section, STRING_DUMP);
|
|
|
|
|
else
|
|
|
|
|
request_dump_byname (optarg, STRING_DUMP);
|
|
|
|
|
request_dump (STRING_DUMP);
|
|
|
|
|
break;
|
|
|
|
|
case 'R':
|
|
|
|
|
request_dump (RELOC_DUMP);
|
|
|
|
|
break;
|
|
|
|
|
case 'w':
|
|
|
|
|
do_dump++;
|
|
|
|
@ -3088,12 +3098,8 @@ parse_args (int argc, char ** argv)
|
|
|
|
|
break;
|
|
|
|
|
#ifdef SUPPORT_DISASSEMBLY
|
|
|
|
|
case 'i':
|
|
|
|
|
do_dump++;
|
|
|
|
|
section = strtoul (optarg, & cp, 0);
|
|
|
|
|
if (! *cp && section >= 0)
|
|
|
|
|
request_dump_bynumber (section, DISASS_DUMP);
|
|
|
|
|
else
|
|
|
|
|
request_dump_byname (optarg, DISASS_DUMP);
|
|
|
|
|
request_dump (DISASS_DUMP);
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
case 'v':
|
|
|
|
|
print_version (program_name);
|
|
|
|
@ -7759,190 +7765,57 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED)
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef SUPPORT_DISASSEMBLY
|
|
|
|
|
static int
|
|
|
|
|
disassemble_section (Elf_Internal_Shdr * section, FILE * file)
|
|
|
|
|
/* Check to see if the given reloc needs to be handled in a target specific
|
|
|
|
|
manner. If so then process the reloc and return TRUE otherwise return
|
|
|
|
|
FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
|
|
|
|
unsigned char * start,
|
|
|
|
|
Elf_Internal_Sym * symtab)
|
|
|
|
|
{
|
|
|
|
|
printf (_("\nAssembly dump of section %s\n"),
|
|
|
|
|
SECTION_NAME (section));
|
|
|
|
|
unsigned int reloc_type = get_reloc_type (reloc->r_info);
|
|
|
|
|
|
|
|
|
|
/* XXX -- to be done --- XXX */
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
|
|
|
|
|
{
|
|
|
|
|
Elf_Internal_Shdr * relsec;
|
|
|
|
|
bfd_size_type num_bytes;
|
|
|
|
|
bfd_vma addr;
|
|
|
|
|
char * data;
|
|
|
|
|
char * end;
|
|
|
|
|
char * start;
|
|
|
|
|
char * name = SECTION_NAME (section);
|
|
|
|
|
bfd_boolean some_strings_shown;
|
|
|
|
|
|
|
|
|
|
num_bytes = section->sh_size;
|
|
|
|
|
|
|
|
|
|
if (num_bytes == 0 || section->sh_type == SHT_NOBITS)
|
|
|
|
|
switch (elf_header.e_machine)
|
|
|
|
|
{
|
|
|
|
|
printf (_("\nSection '%s' has no data to dump.\n"), name);
|
|
|
|
|
return 0;
|
|
|
|
|
case EM_MN10300:
|
|
|
|
|
case EM_CYGNUS_MN10300:
|
|
|
|
|
{
|
|
|
|
|
static Elf_Internal_Sym * saved_sym = NULL;
|
|
|
|
|
|
|
|
|
|
switch (reloc_type)
|
|
|
|
|
{
|
|
|
|
|
case 34: /* R_MN10300_ALIGN */
|
|
|
|
|
return TRUE;
|
|
|
|
|
case 33: /* R_MN10300_SYM_DIFF */
|
|
|
|
|
saved_sym = symtab + get_reloc_symindex (reloc->r_info);
|
|
|
|
|
return TRUE;
|
|
|
|
|
case 1: /* R_MN10300_32 */
|
|
|
|
|
case 2: /* R_MN10300_16 */
|
|
|
|
|
if (saved_sym != NULL)
|
|
|
|
|
{
|
|
|
|
|
bfd_vma value;
|
|
|
|
|
|
|
|
|
|
value = reloc->r_addend
|
|
|
|
|
+ (symtab[get_reloc_symindex (reloc->r_info)].st_value
|
|
|
|
|
- saved_sym->st_value);
|
|
|
|
|
|
|
|
|
|
byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2);
|
|
|
|
|
|
|
|
|
|
saved_sym = NULL;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
if (saved_sym != NULL)
|
|
|
|
|
error (_("Unhandled MN10300 reloc type found after SYM_DIFF reloc"));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr = section->sh_addr;
|
|
|
|
|
|
|
|
|
|
start = get_data (NULL, file, section->sh_offset, 1, num_bytes,
|
|
|
|
|
_("section data"));
|
|
|
|
|
if (!start)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
printf (_("\nString dump of section '%s':\n"), name);
|
|
|
|
|
|
|
|
|
|
/* If the section being dumped has relocations against it the user might
|
|
|
|
|
be expecting these relocations to have been applied. Check for this
|
|
|
|
|
case and issue a warning message in order to avoid confusion.
|
|
|
|
|
FIXME: Maybe we ought to have an option that dumps a section with
|
|
|
|
|
relocs applied ? */
|
|
|
|
|
for (relsec = section_headers;
|
|
|
|
|
relsec < section_headers + elf_header.e_shnum;
|
|
|
|
|
++relsec)
|
|
|
|
|
{
|
|
|
|
|
if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
|
|
|
|
|
|| relsec->sh_info >= elf_header.e_shnum
|
|
|
|
|
|| section_headers + relsec->sh_info != section
|
|
|
|
|
|| relsec->sh_size == 0
|
|
|
|
|
|| relsec->sh_link >= elf_header.e_shnum)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
printf (_(" Note: This section has relocations against it, but these have NOT been applied to this dump.\n"));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data = start;
|
|
|
|
|
end = start + num_bytes;
|
|
|
|
|
some_strings_shown = FALSE;
|
|
|
|
|
|
|
|
|
|
while (data < end)
|
|
|
|
|
{
|
|
|
|
|
while (!ISPRINT (* data))
|
|
|
|
|
if (++ data >= end)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (data < end)
|
|
|
|
|
{
|
|
|
|
|
#ifndef __MSVCRT__
|
|
|
|
|
printf (" [%6tx] %s\n", data - start, data);
|
|
|
|
|
#else
|
|
|
|
|
printf (" [%6Ix] %s\n", (size_t) (data - start), data);
|
|
|
|
|
#endif
|
|
|
|
|
data += strlen (data);
|
|
|
|
|
some_strings_shown = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! some_strings_shown)
|
|
|
|
|
printf (_(" No strings found in this section."));
|
|
|
|
|
|
|
|
|
|
free (start);
|
|
|
|
|
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
dump_section_as_bytes (Elf_Internal_Shdr * section, FILE * file)
|
|
|
|
|
{
|
|
|
|
|
Elf_Internal_Shdr * relsec;
|
|
|
|
|
bfd_size_type bytes;
|
|
|
|
|
bfd_vma addr;
|
|
|
|
|
unsigned char * data;
|
|
|
|
|
unsigned char * start;
|
|
|
|
|
|
|
|
|
|
bytes = section->sh_size;
|
|
|
|
|
|
|
|
|
|
if (bytes == 0 || section->sh_type == SHT_NOBITS)
|
|
|
|
|
{
|
|
|
|
|
printf (_("\nSection '%s' has no data to dump.\n"),
|
|
|
|
|
SECTION_NAME (section));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
|
|
|
|
|
|
|
|
|
|
addr = section->sh_addr;
|
|
|
|
|
|
|
|
|
|
start = get_data (NULL, file, section->sh_offset, 1, bytes,
|
|
|
|
|
_("section data"));
|
|
|
|
|
if (!start)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* If the section being dumped has relocations against it the user might
|
|
|
|
|
be expecting these relocations to have been applied. Check for this
|
|
|
|
|
case and issue a warning message in order to avoid confusion.
|
|
|
|
|
FIXME: Maybe we ought to have an option that dumps a section with
|
|
|
|
|
relocs applied ? */
|
|
|
|
|
for (relsec = section_headers;
|
|
|
|
|
relsec < section_headers + elf_header.e_shnum;
|
|
|
|
|
++relsec)
|
|
|
|
|
{
|
|
|
|
|
if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
|
|
|
|
|
|| relsec->sh_info >= elf_header.e_shnum
|
|
|
|
|
|| section_headers + relsec->sh_info != section
|
|
|
|
|
|| relsec->sh_size == 0
|
|
|
|
|
|| relsec->sh_link >= elf_header.e_shnum)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data = start;
|
|
|
|
|
|
|
|
|
|
while (bytes)
|
|
|
|
|
{
|
|
|
|
|
int j;
|
|
|
|
|
int k;
|
|
|
|
|
int lbytes;
|
|
|
|
|
|
|
|
|
|
lbytes = (bytes > 16 ? 16 : bytes);
|
|
|
|
|
|
|
|
|
|
printf (" 0x%8.8lx ", (unsigned long) addr);
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < 16; j++)
|
|
|
|
|
{
|
|
|
|
|
if (j < lbytes)
|
|
|
|
|
printf ("%2.2x", data[j]);
|
|
|
|
|
else
|
|
|
|
|
printf (" ");
|
|
|
|
|
|
|
|
|
|
if ((j & 3) == 3)
|
|
|
|
|
printf (" ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < lbytes; j++)
|
|
|
|
|
{
|
|
|
|
|
k = data[j];
|
|
|
|
|
if (k >= ' ' && k < 0x7f)
|
|
|
|
|
printf ("%c", k);
|
|
|
|
|
else
|
|
|
|
|
printf (".");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
|
|
|
|
|
data += lbytes;
|
|
|
|
|
addr += lbytes;
|
|
|
|
|
bytes -= lbytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free (start);
|
|
|
|
|
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
return 1;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns TRUE iff RELOC_TYPE is a 32-bit absolute RELA relocation used in
|
|
|
|
@ -8130,8 +8003,8 @@ is_32bit_pcrel_reloc (unsigned int reloc_type)
|
|
|
|
|
/* Do not abort or issue an error message here. Not all targets use
|
|
|
|
|
pc-relative 32-bit relocs in their DWARF debug information and we
|
|
|
|
|
have already tested for target coverage in is_32bit_abs_reloc. A
|
|
|
|
|
more helpful warning message will be generated by
|
|
|
|
|
debug_apply_relocations anyway, so just return. */
|
|
|
|
|
more helpful warning message will be generated by apply_relocations
|
|
|
|
|
anyway, so just return. */
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -8265,133 +8138,15 @@ is_none_reloc (unsigned int reloc_type)
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Uncompresses a section that was compressed using zlib, in place.
|
|
|
|
|
This is a copy of bfd_uncompress_section_contents, in bfd/compress.c */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
uncompress_section_contents (unsigned char ** buffer, dwarf_size_type * size)
|
|
|
|
|
{
|
|
|
|
|
#ifndef HAVE_ZLIB_H
|
|
|
|
|
/* These are just to quiet gcc. */
|
|
|
|
|
buffer = 0;
|
|
|
|
|
size = 0;
|
|
|
|
|
return FALSE;
|
|
|
|
|
#else
|
|
|
|
|
dwarf_size_type compressed_size = *size;
|
|
|
|
|
unsigned char * compressed_buffer = *buffer;
|
|
|
|
|
dwarf_size_type uncompressed_size;
|
|
|
|
|
unsigned char * uncompressed_buffer;
|
|
|
|
|
z_stream strm;
|
|
|
|
|
int rc;
|
|
|
|
|
dwarf_size_type header_size = 12;
|
|
|
|
|
|
|
|
|
|
/* Read the zlib header. In this case, it should be "ZLIB" followed
|
|
|
|
|
by the uncompressed section size, 8 bytes in big-endian order. */
|
|
|
|
|
if (compressed_size < header_size
|
|
|
|
|
|| ! streq ((char *) compressed_buffer, "ZLIB"))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[11];
|
|
|
|
|
|
|
|
|
|
/* It is possible the section consists of several compressed
|
|
|
|
|
buffers concatenated together, so we uncompress in a loop. */
|
|
|
|
|
strm.zalloc = NULL;
|
|
|
|
|
strm.zfree = NULL;
|
|
|
|
|
strm.opaque = NULL;
|
|
|
|
|
strm.avail_in = compressed_size - header_size;
|
|
|
|
|
strm.next_in = (Bytef *) compressed_buffer + header_size;
|
|
|
|
|
strm.avail_out = uncompressed_size;
|
|
|
|
|
uncompressed_buffer = xmalloc (uncompressed_size);
|
|
|
|
|
|
|
|
|
|
rc = inflateInit (& strm);
|
|
|
|
|
while (strm.avail_in > 0)
|
|
|
|
|
{
|
|
|
|
|
if (rc != Z_OK)
|
|
|
|
|
goto fail;
|
|
|
|
|
strm.next_out = ((Bytef *) uncompressed_buffer
|
|
|
|
|
+ (uncompressed_size - strm.avail_out));
|
|
|
|
|
rc = inflate (&strm, Z_FINISH);
|
|
|
|
|
if (rc != Z_STREAM_END)
|
|
|
|
|
goto fail;
|
|
|
|
|
rc = inflateReset (& strm);
|
|
|
|
|
}
|
|
|
|
|
rc = inflateEnd (& strm);
|
|
|
|
|
if (rc != Z_OK
|
|
|
|
|
|| strm.avail_out != 0)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
free (compressed_buffer);
|
|
|
|
|
*buffer = uncompressed_buffer;
|
|
|
|
|
*size = uncompressed_size;
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
free (uncompressed_buffer);
|
|
|
|
|
return 0;
|
|
|
|
|
#endif /* HAVE_ZLIB_H */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check to see if the given reloc needs to be handled in a target specific
|
|
|
|
|
manner. If so then process the reloc and return TRUE otherwise return
|
|
|
|
|
FALSE. */
|
|
|
|
|
|
|
|
|
|
static bfd_boolean
|
|
|
|
|
target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
|
|
|
|
unsigned char * start,
|
|
|
|
|
Elf_Internal_Sym * symtab)
|
|
|
|
|
{
|
|
|
|
|
unsigned int reloc_type = get_reloc_type (reloc->r_info);
|
|
|
|
|
|
|
|
|
|
switch (elf_header.e_machine)
|
|
|
|
|
{
|
|
|
|
|
case EM_MN10300:
|
|
|
|
|
case EM_CYGNUS_MN10300:
|
|
|
|
|
{
|
|
|
|
|
static Elf_Internal_Sym * saved_sym = NULL;
|
|
|
|
|
|
|
|
|
|
switch (reloc_type)
|
|
|
|
|
{
|
|
|
|
|
case 34: /* R_MN10300_ALIGN */
|
|
|
|
|
return TRUE;
|
|
|
|
|
case 33: /* R_MN10300_SYM_DIFF */
|
|
|
|
|
saved_sym = symtab + get_reloc_symindex (reloc->r_info);
|
|
|
|
|
return TRUE;
|
|
|
|
|
case 1: /* R_MN10300_32 */
|
|
|
|
|
if (saved_sym != NULL)
|
|
|
|
|
{
|
|
|
|
|
bfd_vma value;
|
|
|
|
|
|
|
|
|
|
value = reloc->r_addend
|
|
|
|
|
+ (symtab[get_reloc_symindex (reloc->r_info)].st_value
|
|
|
|
|
- saved_sym->st_value);
|
|
|
|
|
|
|
|
|
|
byte_put (start + reloc->r_offset, value, 4);
|
|
|
|
|
|
|
|
|
|
saved_sym = NULL;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Apply relocations to a debug section. */
|
|
|
|
|
/* Apply relocations to a section.
|
|
|
|
|
Note: So far support has been added only for those relocations
|
|
|
|
|
which can be found in debug sections.
|
|
|
|
|
FIXME: Add support for more relocations ? */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
debug_apply_relocations (void * file,
|
|
|
|
|
Elf_Internal_Shdr * section,
|
|
|
|
|
unsigned char * start)
|
|
|
|
|
apply_relocations (void * file,
|
|
|
|
|
Elf_Internal_Shdr * section,
|
|
|
|
|
unsigned char * start)
|
|
|
|
|
{
|
|
|
|
|
Elf_Internal_Shdr * relsec;
|
|
|
|
|
unsigned char * end = start + section->sh_size;
|
|
|
|
@ -8399,7 +8154,7 @@ debug_apply_relocations (void * file,
|
|
|
|
|
if (elf_header.e_type != ET_REL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Find the reloc section associated with the debug section. */
|
|
|
|
|
/* Find the reloc section associated with the section. */
|
|
|
|
|
for (relsec = section_headers;
|
|
|
|
|
relsec < section_headers + elf_header.e_shnum;
|
|
|
|
|
++relsec)
|
|
|
|
@ -8524,6 +8279,274 @@ debug_apply_relocations (void * file,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef SUPPORT_DISASSEMBLY
|
|
|
|
|
static int
|
|
|
|
|
disassemble_section (Elf_Internal_Shdr * section, FILE * file)
|
|
|
|
|
{
|
|
|
|
|
printf (_("\nAssembly dump of section %s\n"),
|
|
|
|
|
SECTION_NAME (section));
|
|
|
|
|
|
|
|
|
|
/* XXX -- to be done --- XXX */
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Reads in the contents of SECTION from FILE, returning a pointer
|
|
|
|
|
to a malloc'ed buffer or NULL if something went wrong. */
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
get_section_contents (Elf_Internal_Shdr * section, FILE * file)
|
|
|
|
|
{
|
|
|
|
|
bfd_size_type num_bytes;
|
|
|
|
|
|
|
|
|
|
num_bytes = section->sh_size;
|
|
|
|
|
|
|
|
|
|
if (num_bytes == 0 || section->sh_type == SHT_NOBITS)
|
|
|
|
|
{
|
|
|
|
|
printf (_("\nSection '%s' has no data to dump.\n"),
|
|
|
|
|
SECTION_NAME (section));
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return get_data (NULL, file, section->sh_offset, 1, num_bytes,
|
|
|
|
|
_("section contents"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file)
|
|
|
|
|
{
|
|
|
|
|
Elf_Internal_Shdr * relsec;
|
|
|
|
|
bfd_size_type num_bytes;
|
|
|
|
|
bfd_vma addr;
|
|
|
|
|
char * data;
|
|
|
|
|
char * end;
|
|
|
|
|
char * start;
|
|
|
|
|
char * name = SECTION_NAME (section);
|
|
|
|
|
bfd_boolean some_strings_shown;
|
|
|
|
|
|
|
|
|
|
start = get_section_contents (section, file);
|
|
|
|
|
if (start == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
printf (_("\nString dump of section '%s':\n"), name);
|
|
|
|
|
|
|
|
|
|
/* If the section being dumped has relocations against it the user might
|
|
|
|
|
be expecting these relocations to have been applied. Check for this
|
|
|
|
|
case and issue a warning message in order to avoid confusion.
|
|
|
|
|
FIXME: Maybe we ought to have an option that dumps a section with
|
|
|
|
|
relocs applied ? */
|
|
|
|
|
for (relsec = section_headers;
|
|
|
|
|
relsec < section_headers + elf_header.e_shnum;
|
|
|
|
|
++relsec)
|
|
|
|
|
{
|
|
|
|
|
if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
|
|
|
|
|
|| relsec->sh_info >= elf_header.e_shnum
|
|
|
|
|
|| section_headers + relsec->sh_info != section
|
|
|
|
|
|| relsec->sh_size == 0
|
|
|
|
|
|| relsec->sh_link >= elf_header.e_shnum)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
printf (_(" Note: This section has relocations against it, but these have NOT been applied to this dump.\n"));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
num_bytes = section->sh_size;
|
|
|
|
|
addr = section->sh_addr;
|
|
|
|
|
data = start;
|
|
|
|
|
end = start + num_bytes;
|
|
|
|
|
some_strings_shown = FALSE;
|
|
|
|
|
|
|
|
|
|
while (data < end)
|
|
|
|
|
{
|
|
|
|
|
while (!ISPRINT (* data))
|
|
|
|
|
if (++ data >= end)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (data < end)
|
|
|
|
|
{
|
|
|
|
|
#ifndef __MSVCRT__
|
|
|
|
|
printf (" [%6tx] %s\n", data - start, data);
|
|
|
|
|
#else
|
|
|
|
|
printf (" [%6Ix] %s\n", (size_t) (data - start), data);
|
|
|
|
|
#endif
|
|
|
|
|
data += strlen (data);
|
|
|
|
|
some_strings_shown = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! some_strings_shown)
|
|
|
|
|
printf (_(" No strings found in this section."));
|
|
|
|
|
|
|
|
|
|
free (start);
|
|
|
|
|
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
dump_section_as_bytes (Elf_Internal_Shdr * section,
|
|
|
|
|
FILE * file,
|
|
|
|
|
bfd_boolean relocate)
|
|
|
|
|
{
|
|
|
|
|
Elf_Internal_Shdr * relsec;
|
|
|
|
|
bfd_size_type bytes;
|
|
|
|
|
bfd_vma addr;
|
|
|
|
|
unsigned char * data;
|
|
|
|
|
unsigned char * start;
|
|
|
|
|
|
|
|
|
|
start = (unsigned char *) get_section_contents (section, file);
|
|
|
|
|
if (start == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section));
|
|
|
|
|
|
|
|
|
|
if (relocate)
|
|
|
|
|
{
|
|
|
|
|
apply_relocations (file, section, start);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If the section being dumped has relocations against it the user might
|
|
|
|
|
be expecting these relocations to have been applied. Check for this
|
|
|
|
|
case and issue a warning message in order to avoid confusion.
|
|
|
|
|
FIXME: Maybe we ought to have an option that dumps a section with
|
|
|
|
|
relocs applied ? */
|
|
|
|
|
for (relsec = section_headers;
|
|
|
|
|
relsec < section_headers + elf_header.e_shnum;
|
|
|
|
|
++relsec)
|
|
|
|
|
{
|
|
|
|
|
if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
|
|
|
|
|
|| relsec->sh_info >= elf_header.e_shnum
|
|
|
|
|
|| section_headers + relsec->sh_info != section
|
|
|
|
|
|| relsec->sh_size == 0
|
|
|
|
|
|| relsec->sh_link >= elf_header.e_shnum)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
printf (_(" NOTE: This section has relocations against it, but these have NOT been applied to this dump.\n"));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addr = section->sh_addr;
|
|
|
|
|
bytes = section->sh_size;
|
|
|
|
|
data = start;
|
|
|
|
|
|
|
|
|
|
while (bytes)
|
|
|
|
|
{
|
|
|
|
|
int j;
|
|
|
|
|
int k;
|
|
|
|
|
int lbytes;
|
|
|
|
|
|
|
|
|
|
lbytes = (bytes > 16 ? 16 : bytes);
|
|
|
|
|
|
|
|
|
|
printf (" 0x%8.8lx ", (unsigned long) addr);
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < 16; j++)
|
|
|
|
|
{
|
|
|
|
|
if (j < lbytes)
|
|
|
|
|
printf ("%2.2x", data[j]);
|
|
|
|
|
else
|
|
|
|
|
printf (" ");
|
|
|
|
|
|
|
|
|
|
if ((j & 3) == 3)
|
|
|
|
|
printf (" ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < lbytes; j++)
|
|
|
|
|
{
|
|
|
|
|
k = data[j];
|
|
|
|
|
if (k >= ' ' && k < 0x7f)
|
|
|
|
|
printf ("%c", k);
|
|
|
|
|
else
|
|
|
|
|
printf (".");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
|
|
|
|
|
data += lbytes;
|
|
|
|
|
addr += lbytes;
|
|
|
|
|
bytes -= lbytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free (start);
|
|
|
|
|
|
|
|
|
|
putchar ('\n');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Uncompresses a section that was compressed using zlib, in place.
|
|
|
|
|
This is a copy of bfd_uncompress_section_contents, in bfd/compress.c */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
uncompress_section_contents (unsigned char ** buffer, dwarf_size_type * size)
|
|
|
|
|
{
|
|
|
|
|
#ifndef HAVE_ZLIB_H
|
|
|
|
|
/* These are just to quiet gcc. */
|
|
|
|
|
buffer = 0;
|
|
|
|
|
size = 0;
|
|
|
|
|
return FALSE;
|
|
|
|
|
#else
|
|
|
|
|
dwarf_size_type compressed_size = *size;
|
|
|
|
|
unsigned char * compressed_buffer = *buffer;
|
|
|
|
|
dwarf_size_type uncompressed_size;
|
|
|
|
|
unsigned char * uncompressed_buffer;
|
|
|
|
|
z_stream strm;
|
|
|
|
|
int rc;
|
|
|
|
|
dwarf_size_type header_size = 12;
|
|
|
|
|
|
|
|
|
|
/* Read the zlib header. In this case, it should be "ZLIB" followed
|
|
|
|
|
by the uncompressed section size, 8 bytes in big-endian order. */
|
|
|
|
|
if (compressed_size < header_size
|
|
|
|
|
|| ! streq ((char *) compressed_buffer, "ZLIB"))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
|
|
|
|
|
uncompressed_size += compressed_buffer[11];
|
|
|
|
|
|
|
|
|
|
/* It is possible the section consists of several compressed
|
|
|
|
|
buffers concatenated together, so we uncompress in a loop. */
|
|
|
|
|
strm.zalloc = NULL;
|
|
|
|
|
strm.zfree = NULL;
|
|
|
|
|
strm.opaque = NULL;
|
|
|
|
|
strm.avail_in = compressed_size - header_size;
|
|
|
|
|
strm.next_in = (Bytef *) compressed_buffer + header_size;
|
|
|
|
|
strm.avail_out = uncompressed_size;
|
|
|
|
|
uncompressed_buffer = xmalloc (uncompressed_size);
|
|
|
|
|
|
|
|
|
|
rc = inflateInit (& strm);
|
|
|
|
|
while (strm.avail_in > 0)
|
|
|
|
|
{
|
|
|
|
|
if (rc != Z_OK)
|
|
|
|
|
goto fail;
|
|
|
|
|
strm.next_out = ((Bytef *) uncompressed_buffer
|
|
|
|
|
+ (uncompressed_size - strm.avail_out));
|
|
|
|
|
rc = inflate (&strm, Z_FINISH);
|
|
|
|
|
if (rc != Z_STREAM_END)
|
|
|
|
|
goto fail;
|
|
|
|
|
rc = inflateReset (& strm);
|
|
|
|
|
}
|
|
|
|
|
rc = inflateEnd (& strm);
|
|
|
|
|
if (rc != Z_OK
|
|
|
|
|
|| strm.avail_out != 0)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
free (compressed_buffer);
|
|
|
|
|
*buffer = uncompressed_buffer;
|
|
|
|
|
*size = uncompressed_size;
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
free (uncompressed_buffer);
|
|
|
|
|
return 0;
|
|
|
|
|
#endif /* HAVE_ZLIB_H */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
load_specific_debug_section (enum dwarf_section_display_enum debug,
|
|
|
|
|
Elf_Internal_Shdr * sec, void * file)
|
|
|
|
@ -8551,7 +8574,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (debug_displays [debug].relocate)
|
|
|
|
|
debug_apply_relocations (file, sec, section->start);
|
|
|
|
|
apply_relocations (file, sec, section->start);
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
@ -8700,13 +8723,16 @@ process_section_contents (FILE * file)
|
|
|
|
|
disassemble_section (section, file);
|
|
|
|
|
#endif
|
|
|
|
|
if (dump_sects[i] & HEX_DUMP)
|
|
|
|
|
dump_section_as_bytes (section, file);
|
|
|
|
|
dump_section_as_bytes (section, file, FALSE);
|
|
|
|
|
|
|
|
|
|
if (dump_sects[i] & DEBUG_DUMP)
|
|
|
|
|
display_debug_section (section, file);
|
|
|
|
|
if (dump_sects[i] & RELOC_DUMP)
|
|
|
|
|
dump_section_as_bytes (section, file, TRUE);
|
|
|
|
|
|
|
|
|
|
if (dump_sects[i] & STRING_DUMP)
|
|
|
|
|
dump_section_as_strings (section, file);
|
|
|
|
|
|
|
|
|
|
if (dump_sects[i] & DEBUG_DUMP)
|
|
|
|
|
display_debug_section (section, file);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check to see if the user requested a
|
|
|
|
|