You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
\f
/* The difference between readelf and objdump:
#include "libiberty.h"
char *program_name = "readelf";
-long archive_file_offset;
-unsigned long archive_file_size;
-unsigned long dynamic_addr;
-bfd_size_type dynamic_size;
-unsigned int dynamic_nent;
-char *dynamic_strings;
-unsigned long dynamic_strings_length;
-char *string_table;
-unsigned long string_table_length;
-unsigned long num_dynamic_syms;
-Elf_Internal_Sym *dynamic_symbols;
-Elf_Internal_Syminfo *dynamic_syminfo;
-unsigned long dynamic_syminfo_offset;
-unsigned int dynamic_syminfo_nent;
-char program_interpreter[64];
-bfd_vma dynamic_info[DT_JMPREL + 1];
-bfd_vma version_info[16];
-Elf_Internal_Ehdr elf_header;
-Elf_Internal_Shdr *section_headers;
-Elf_Internal_Phdr *program_headers;
-Elf_Internal_Dyn *dynamic_section;
-Elf_Internal_Shdr *symtab_shndx_hdr;
-int show_name;
-int do_dynamic;
-int do_syms;
-int do_reloc;
-int do_sections;
-int do_section_groups;
-int do_segments;
-int do_unwind;
-int do_using_dynamic;
-int do_header;
-int do_dump;
-int do_version;
-int do_wide;
-int do_histogram;
-int do_debugging;
-int do_debug_info;
-int do_debug_abbrevs;
-int do_debug_lines;
-int do_debug_pubnames;
-int do_debug_aranges;
-int do_debug_ranges;
-int do_debug_frames;
-int do_debug_frames_interp;
-int do_debug_macinfo;
-int do_debug_str;
-int do_debug_loc;
-int do_arch;
-int do_notes;
-int is_32bit_elf;
-int have_frame_base;
-int need_base_address;
-bfd_vma eh_addr_size;
+static long archive_file_offset;
+static unsigned long archive_file_size;
+static unsigned long dynamic_addr;
+static bfd_size_type dynamic_size;
+static unsigned int dynamic_nent;
+static char *dynamic_strings;
+static unsigned long dynamic_strings_length;
+static char *string_table;
+static unsigned long string_table_length;
+static unsigned long num_dynamic_syms;
+static Elf_Internal_Sym *dynamic_symbols;
+static Elf_Internal_Syminfo *dynamic_syminfo;
+static unsigned long dynamic_syminfo_offset;
+static unsigned int dynamic_syminfo_nent;
+static char program_interpreter[64];
+static bfd_vma dynamic_info[DT_JMPREL + 1];
+static bfd_vma version_info[16];
+static Elf_Internal_Ehdr elf_header;
+static Elf_Internal_Shdr *section_headers;
+static Elf_Internal_Phdr *program_headers;
+static Elf_Internal_Dyn *dynamic_section;
+static Elf_Internal_Shdr *symtab_shndx_hdr;
+static int show_name;
+static int do_dynamic;
+static int do_syms;
+static int do_reloc;
+static int do_sections;
+static int do_section_groups;
+static int do_full_section_name;
+static int do_segments;
+static int do_unwind;
+static int do_using_dynamic;
+static int do_header;
+static int do_dump;
+static int do_version;
+static int do_wide;
+static int do_histogram;
+static int do_debugging;
+static int do_debug_info;
+static int do_debug_abbrevs;
+static int do_debug_lines;
+static int do_debug_pubnames;
+static int do_debug_aranges;
+static int do_debug_ranges;
+static int do_debug_frames;
+static int do_debug_frames_interp;
+static int do_debug_macinfo;
+static int do_debug_str;
+static int do_debug_loc;
+static int do_arch;
+static int do_notes;
+static int is_32bit_elf;
+static int have_frame_base;
+static int need_base_address;
+static bfd_vma eh_addr_size;
struct group_list
{
unsigned int group_index;
};
-struct group *section_groups;
-size_t group_count;
-
-struct group **section_headers_groups;
+static size_t group_count;
+static struct group *section_groups;
+static struct group **section_headers_groups;
/* A dynamic array of flags indicating for which sections a hex dump
has been requested (via the -x switch) and/or a disassembly dump
}
}
+static const char *
+get_ppc_dynamic_type (unsigned long type)
+{
+ switch (type)
+ {
+ case DT_PPC_GLINK: return "PPC_GLINK";
+ default:
+ return NULL;
+ }
+}
+
static const char *
get_ppc64_dynamic_type (unsigned long type)
{
static const char *
get_dynamic_type (unsigned long type)
{
- static char buff[32];
+ static char buff[64];
switch (type)
{
case EM_SPARCV9:
result = get_sparc64_dynamic_type (type);
break;
+ case EM_PPC:
+ result = get_ppc_dynamic_type (type);
+ break;
case EM_PPC64:
result = get_ppc64_dynamic_type (type);
break;
if (result != NULL)
return result;
- sprintf (buff, _("Processor Specific: %lx"), type);
+ snprintf (buff, sizeof (buff), _("Processor Specific: %lx"), type);
}
else if ((type >= DT_LOOS) && (type <= DT_HIOS))
{
if (result != NULL)
return result;
- sprintf (buff, _("Operating System specific: %lx"), type);
+ snprintf (buff, sizeof (buff), _("Operating System specific: %lx"),
+ type);
}
else
- sprintf (buff, _("<unknown>: %lx"), type);
+ snprintf (buff, sizeof (buff), _("<unknown>: %lx"), type);
return buff;
}
default:
if ((e_type >= ET_LOPROC) && (e_type <= ET_HIPROC))
- sprintf (buff, _("Processor Specific: (%x)"), e_type);
+ snprintf (buff, sizeof (buff), _("Processor Specific: (%x)"), e_type);
else if ((e_type >= ET_LOOS) && (e_type <= ET_HIOS))
- sprintf (buff, _("OS Specific: (%x)"), e_type);
+ snprintf (buff, sizeof (buff), _("OS Specific: (%x)"), e_type);
else
- sprintf (buff, _("<unknown>: %x"), e_type);
+ snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_type);
return buff;
}
}
case EM_XTENSA_OLD:
case EM_XTENSA: return "Tensilica Xtensa Processor";
default:
- sprintf (buff, _("<unknown>: %x"), e_machine);
+ snprintf (buff, sizeof (buff), _("<unknown>: %x"), e_machine);
return buff;
}
}
case ELFOSABI_STANDALONE: return _("Standalone App");
case ELFOSABI_ARM: return "ARM";
default:
- sprintf (buff, _("<unknown: %x>"), osabi);
+ snprintf (buff, sizeof (buff), _("<unknown: %x>"), osabi);
return buff;
}
}
+static const char *
+get_arm_segment_type (unsigned long type)
+{
+ switch (type)
+ {
+ case PT_ARM_EXIDX:
+ return "EXIDX";
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
static const char *
get_mips_segment_type (unsigned long type)
{
switch (elf_header.e_machine)
{
+ case EM_ARM:
+ result = get_arm_segment_type (p_type);
+ break;
case EM_MIPS:
case EM_MIPS_RS3_LE:
result = get_mips_segment_type (p_type);
sprintf (buff, "LOOS+%lx", p_type - PT_LOOS);
}
else
- sprintf (buff, _("<unknown>: %lx"), p_type);
+ snprintf (buff, sizeof (buff), _("<unknown>: %lx"), p_type);
return buff;
}
else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER);
else
- sprintf (buff, _("<unknown>: %x"), sh_type);
+ snprintf (buff, sizeof (buff), _("<unknown>: %x"), sh_type);
return buff;
}
#define OPTION_DEBUG_DUMP 512
-struct option options[] =
+static struct option options[] =
{
{"all", no_argument, 0, 'a'},
{"file-header", no_argument, 0, 'h'},
{"sections", no_argument, 0, 'S'},
{"section-headers", no_argument, 0, 'S'},
{"section-groups", no_argument, 0, 'g'},
+ {"full-section-name",no_argument, 0, 'N'},
{"symbols", no_argument, 0, 's'},
{"syms", no_argument, 0, 's'},
{"relocs", no_argument, 0, 'r'},
-S --section-headers Display the sections' header\n\
--sections An alias for --section-headers\n\
-g --section-groups Display the section groups\n\
+ -N --full-section-name\n\
+ Display the full section name\n\
-e --headers Equivalent to: -h -l -S\n\
-s --syms Display the symbol table\n\
--symbols An alias for --syms\n\
usage ();
while ((c = getopt_long
- (argc, argv, "ersuahnldSDAIgw::x:i:vVWH", options, NULL)) != EOF)
+ (argc, argv, "ersuahnldSDAINgw::x:i:vVWH", options, NULL)) != EOF)
{
char *cp;
int section;
case 'g':
do_section_groups++;
break;
+ case 'N':
+ do_full_section_name++;
+ break;
case 'e':
do_header++;
do_sections++;
case ELFCLASS32: return "ELF32";
case ELFCLASS64: return "ELF64";
default:
- sprintf (buff, _("<unknown: %x>"), elf_class);
+ snprintf (buff, sizeof (buff), _("<unknown: %x>"), elf_class);
return buff;
}
}
case ELFDATA2LSB: return _("2's complement, little endian");
case ELFDATA2MSB: return _("2's complement, big endian");
default:
- sprintf (buff, _("<unknown: %x>"), encoding);
+ snprintf (buff, sizeof (buff), _("<unknown: %x>"), encoding);
return buff;
}
}
static const char *
get_elf_section_flags (bfd_vma sh_flags)
{
- static char buff[32];
-
- *buff = 0;
+ static char buff[33];
+ char *p = buff;
while (sh_flags)
{
switch (flag)
{
- case SHF_WRITE: strcat (buff, "W"); break;
- case SHF_ALLOC: strcat (buff, "A"); break;
- case SHF_EXECINSTR: strcat (buff, "X"); break;
- case SHF_MERGE: strcat (buff, "M"); break;
- case SHF_STRINGS: strcat (buff, "S"); break;
- case SHF_INFO_LINK: strcat (buff, "I"); break;
- case SHF_LINK_ORDER: strcat (buff, "L"); break;
- case SHF_OS_NONCONFORMING: strcat (buff, "O"); break;
- case SHF_GROUP: strcat (buff, "G"); break;
- case SHF_TLS: strcat (buff, "T"); break;
+ case SHF_WRITE: *p = 'W'; break;
+ case SHF_ALLOC: *p = 'A'; break;
+ case SHF_EXECINSTR: *p = 'X'; break;
+ case SHF_MERGE: *p = 'M'; break;
+ case SHF_STRINGS: *p = 'S'; break;
+ case SHF_INFO_LINK: *p = 'I'; break;
+ case SHF_LINK_ORDER: *p = 'L'; break;
+ case SHF_OS_NONCONFORMING: *p = 'O'; break;
+ case SHF_GROUP: *p = 'G'; break;
+ case SHF_TLS: *p = 'T'; break;
default:
if (flag & SHF_MASKOS)
{
- strcat (buff, "o");
+ *p = 'o';
sh_flags &= ~ SHF_MASKOS;
}
else if (flag & SHF_MASKPROC)
{
- strcat (buff, "p");
+ *p = 'p';
sh_flags &= ~ SHF_MASKPROC;
}
else
- strcat (buff, "x");
+ *p = 'x';
break;
}
+ p++;
}
+ *p = '\0';
return buff;
}
printf (_("\nSection Header:\n"));
if (is_32bit_elf)
- printf
- (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"));
+ {
+ if (do_full_section_name)
+ {
+ printf (_(" [Nr] Name\n"));
+ printf (_(" Type Addr Off Size ES Flg Lk Inf Al\n"));
+ }
+ else
+ printf
+ (_(" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"));
+ }
else if (do_wide)
- printf
- (_(" [Nr] Name Type Address Off Size ES Flg Lk Inf Al\n"));
+ {
+ if (do_full_section_name)
+ {
+ printf (_(" [Nr] Name\n"));
+ printf (_(" Type Address Off Size ES Flg Lk Inf Al\n"));
+ }
+ else
+ printf
+ (_(" [Nr] Name Type Address Off Size ES Flg Lk Inf Al\n"));
+ }
else
{
- printf (_(" [Nr] Name Type Address Offset\n"));
- printf (_(" Size EntSize Flags Link Info Align\n"));
+ if (do_full_section_name)
+ {
+ printf (_(" [Nr] Name\n"));
+ printf (_(" Flags Type Address Offset\n"));
+ printf (_(" Size EntSize Link Info Align\n"));
+ }
+ else
+ {
+ printf (_(" [Nr] Name Type Address Offset\n"));
+ printf (_(" Size EntSize Flags Link Info Align\n"));
+ }
}
for (i = 0, section = section_headers;
i < elf_header.e_shnum;
i++, section++)
{
- printf (" [%2u] %-17.17s %-15.15s ",
- SECTION_HEADER_NUM (i),
- SECTION_NAME (section),
- get_section_type_name (section->sh_type));
+ if (do_full_section_name)
+ {
+ printf (" [%2u] %s\n",
+ SECTION_HEADER_NUM (i),
+ SECTION_NAME (section));
+ if (is_32bit_elf || do_wide)
+ printf (" %-15.15s ",
+ get_section_type_name (section->sh_type));
+ }
+ else
+ printf (" [%2u] %-17.17s %-15.15s ",
+ SECTION_HEADER_NUM (i),
+ SECTION_NAME (section),
+ get_section_type_name (section->sh_type));
if (is_32bit_elf)
{
putchar ('\n');
}
}
+ else if (do_full_section_name)
+ {
+ printf (" %-15.15s %-15.15s ",
+ get_elf_section_flags (section->sh_flags),
+ get_section_type_name (section->sh_type));
+ putchar (' ');
+ print_vma (section->sh_addr, LONG_HEX);
+ if ((long) section->sh_offset == section->sh_offset)
+ printf (" %8.8lx", (unsigned long) section->sh_offset);
+ else
+ {
+ printf (" ");
+ print_vma (section->sh_offset, LONG_HEX);
+ }
+ printf ("\n ");
+ print_vma (section->sh_size, LONG_HEX);
+ printf (" ");
+ print_vma (section->sh_entsize, LONG_HEX);
+
+ printf (" %2ld %3lu %ld\n",
+ (unsigned long) section->sh_link,
+ (unsigned long) section->sh_info,
+ (unsigned long) section->sh_addralign);
+ }
else
{
putchar (' ');
return "COMDAT";
default:
- sprintf (buff, _("[<unknown>: 0x%x]"), flags);
+ snprintf (buff, sizeof (buff), _("[<unknown>: 0x%x]"), flags);
break;
}
return buff;
return 1;
}
-struct
+static struct
{
const char *name;
int reloc;
time_t time = entry->d_un.d_val;
tmp = gmtime (&time);
- sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
- tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
- tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+ snprintf (timebuf, sizeof (timebuf), "%04u-%02u-%02uT%02u:%02u:%02u",
+ tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
printf ("Time Stamp: %s\n", timebuf);
}
break;
return 1;
}
-static const char *
-get_dynamic_flags (bfd_vma flags)
+static void
+print_dynamic_flags (bfd_vma flags)
{
- static char buff[128];
- char *p = buff;
+ int first = 1;
- *p = '\0';
while (flags)
{
bfd_vma flag;
flag = flags & - flags;
flags &= ~ flag;
- if (p != buff)
- *p++ = ' ';
+ if (first)
+ first = 0;
+ else
+ putc (' ', stdout);
switch (flag)
{
- case DF_ORIGIN: strcpy (p, "ORIGIN"); break;
- case DF_SYMBOLIC: strcpy (p, "SYMBOLIC"); break;
- case DF_TEXTREL: strcpy (p, "TEXTREL"); break;
- case DF_BIND_NOW: strcpy (p, "BIND_NOW"); break;
- case DF_STATIC_TLS: strcpy (p, "STATIC_TLS"); break;
- default: strcpy (p, "unknown"); break;
+ case DF_ORIGIN: fputs ("ORIGIN", stdout); break;
+ case DF_SYMBOLIC: fputs ("SYMBOLIC", stdout); break;
+ case DF_TEXTREL: fputs ("TEXTREL", stdout); break;
+ case DF_BIND_NOW: fputs ("BIND_NOW", stdout); break;
+ case DF_STATIC_TLS: fputs ("STATIC_TLS", stdout); break;
+ default: fputs ("unknown", stdout); break;
}
-
- p = strchr (p, '\0');
}
- return buff;
+ puts ("");
}
/* Parse and display the contents of the dynamic section. */
{
case DT_FLAGS:
if (do_dynamic)
- puts (get_dynamic_flags (entry->d_un.d_val));
+ print_dynamic_flags (entry->d_un.d_val);
break;
case DT_AUXILIARY:
case STB_WEAK: return "WEAK";
default:
if (binding >= STB_LOPROC && binding <= STB_HIPROC)
- sprintf (buff, _("<processor specific>: %d"), binding);
+ snprintf (buff, sizeof (buff), _("<processor specific>: %d"),
+ binding);
else if (binding >= STB_LOOS && binding <= STB_HIOS)
- sprintf (buff, _("<OS specific>: %d"), binding);
+ snprintf (buff, sizeof (buff), _("<OS specific>: %d"), binding);
else
- sprintf (buff, _("<unknown>: %d"), binding);
+ snprintf (buff, sizeof (buff), _("<unknown>: %d"), binding);
return buff;
}
}
if (elf_header.e_machine == EM_PARISC && type == STT_PARISC_MILLI)
return "PARISC_MILLI";
- sprintf (buff, _("<processor specific>: %d"), type);
+ snprintf (buff, sizeof (buff), _("<processor specific>: %d"), type);
}
else if (type >= STT_LOOS && type <= STT_HIOS)
{
return "HP_STUB";
}
- sprintf (buff, _("<OS specific>: %d"), type);
+ snprintf (buff, sizeof (buff), _("<OS specific>: %d"), type);
}
else
- sprintf (buff, _("<unknown>: %d"), type);
+ snprintf (buff, sizeof (buff), _("<unknown>: %d"), type);
return buff;
}
}
example of this see the _clz.o binary in libgcc.a. */
&& ELF32_ST_TYPE (sym->st_info) != STT_OBJECT)
{
- warn (_("%s: skipping unexpected symbol type %s in relocation in section .rela%s\n"),
+ warn (_("skipping unexpected symbol type %s in relocation in section .rela%s\n"),
get_symbol_type (ELF32_ST_TYPE (sym->st_info)),
SECTION_NAME (section));
continue;
}
else
{
+ /* In MIPS little-endian objects, r_info isn't really a
+ 64-bit little-endian value: it has a 32-bit little-endian
+ symbol index followed by four individual byte fields.
+ Reorder INFO accordingly. */
+ if (elf_header.e_machine == EM_MIPS
+ && elf_header.e_ident[EI_DATA] != ELFDATA2MSB)
+ rp->r_info = (((rp->r_info & 0xffffffff) << 32)
+ | ((rp->r_info >> 56) & 0xff)
+ | ((rp->r_info >> 40) & 0xff00)
+ | ((rp->r_info >> 24) & 0xff0000)
+ | ((rp->r_info >> 8) & 0xff000000));
+
sym = symtab + ELF64_R_SYM (rp->r_info);
if (ELF64_R_SYM (rp->r_info) != 0
{
static char buffer[100];
- sprintf (buffer, _("Unknown TAG value: %lx"), tag);
+ snprintf (buffer, sizeof (buffer), _("Unknown TAG value: %lx"), tag);
return buffer;
}
}
{
static char buffer[100];
- sprintf (buffer, _("Unknown FORM value: %lx"), form);
+ snprintf (buffer, sizeof (buffer), _("Unknown FORM value: %lx"), form);
return buffer;
}
}
{
static char buffer[100];
- sprintf (buffer, _("Unknown AT value: %lx"), attribute);
+ snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
+ attribute);
return buffer;
}
}
start += pointer_size;
if (begin == 0 && end == 0)
- break;
+ {
+ printf (_(" %8.8lx <End of list>\n"), offset);
+ break;
+ }
/* Check base address specifiers. */
if (begin == -1UL && end != -1UL)
putchar ('\n');
}
- fputs (_(" <End of list>\n"), stdout);
}
}
putchar ('\n');
case DW_CFA_def_cfa_sf:
fc->cfa_reg = LEB ();
fc->cfa_offset = SLEB ();
+ fc->cfa_offset = fc->cfa_offset * fc->data_factor;
fc->cfa_exp = 0;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_sf: r%d ofs %d\n",
case DW_CFA_def_cfa_offset_sf:
fc->cfa_offset = SLEB ();
+ fc->cfa_offset = fc->cfa_offset * fc->data_factor;
if (! do_debug_frames_interp)
printf (" DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
break;
/* A structure containing the name of a debug section
and a pointer to a function that can decode it. */
-struct
+static struct
{
const char *const name;
int (*display) (Elf_Internal_Shdr *, unsigned char *, FILE *);
liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
tmp = gmtime (&time);
- sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
- tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
- tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+ snprintf (timebuf, sizeof (timebuf),
+ "%04u-%02u-%02uT%02u:%02u:%02u",
+ tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
printf ("%3lu: ", (unsigned long) cnt);
if (VALID_DYNAMIC_NAME (liblist.l_name))
liblist.l_flags = BYTE_GET (elib[cnt].l_flags);
tmp = gmtime (&time);
- sprintf (timebuf, "%04u-%02u-%02uT%02u:%02u:%02u",
- tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
- tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+ snprintf (timebuf, sizeof (timebuf),
+ "%04u-%02u-%02uT%02u:%02u:%02u",
+ tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
printf ("%3lu: ", (unsigned long) cnt);
if (do_wide)
break;
}
- sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
+ snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
return buff;
}
if (e_type < NT_NETBSDCORE_FIRSTMACH)
{
- sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
+ snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
return buff;
}
}
}
- sprintf (buff, _("PT_FIRSTMACH+%d"), e_type - NT_NETBSDCORE_FIRSTMACH);
+ snprintf (buff, sizeof (buff), _("PT_FIRSTMACH+%d"),
+ e_type - NT_NETBSDCORE_FIRSTMACH);
return buff;
}