From 0ccbbcd1244336d38f51648620b32b193d591cbb Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Mon, 4 Jan 2010 21:59:07 -0800 Subject: [PATCH] Make readelf -n check note name strings, handle "VMCOREINFO" flavor. --- backends/ChangeLog | 9 +++++++ backends/i386_corenote.c | 5 ++-- backends/linux-core-note.c | 58 +++++++++++++++++++++++++++++++++++++++------- backends/x86_corenote.c | 5 ++-- libebl/ChangeLog | 8 +++++++ libebl/ebl-hooks.h | 6 ++--- libebl/eblcorenote.c | 14 +++++------ libebl/eblopenbackend.c | 8 +++---- libebl/libebl.h | 10 ++++---- src/ChangeLog | 4 ++++ src/readelf.c | 43 +++++++++++++++++++++++++++++----- 11 files changed, 132 insertions(+), 38 deletions(-) diff --git a/backends/ChangeLog b/backends/ChangeLog index c7f6d36..69351b3 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,12 @@ +2010-01-04 Roland McGrath + + * linux-core-note.c (vmcoreinfo_items): New static const variable. + (EBLHOOK(core_note)): Update arguments for new protocol. + Validate the name as "CORE" or "LINUX" for known n_type cases. + Handle name "VMCOREINFO" n_type=0 with vmcoreinfo_items. + * i386_corenote.c (EXTRA_NOTES): Update parameter usage. + * x86_corenote.c (EXTRA_NOTES_IOPERM): Likewise. + 2009-09-10 Mark Wielaard * sparc_retval.c: Fix license header. diff --git a/backends/i386_corenote.c b/backends/i386_corenote.c index 8989025..40b6a24 100644 --- a/backends/i386_corenote.c +++ b/backends/i386_corenote.c @@ -1,5 +1,5 @@ /* i386 specific core note handling. - Copyright (C) 2007-2009 Red Hat, Inc. + Copyright (C) 2007-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -103,7 +103,8 @@ static const Ebl_Register_Location prxfpreg_regs[] = #define EXTRA_NOTES \ EXTRA_REGSET (NT_PRXFPREG, 512, prxfpreg_regs) \ case NT_386_TLS: \ - return tls_info (descsz, regs_offset, nregloc, reglocs, nitems, items); \ + return tls_info (nhdr->n_descsz, regs_offset, nregloc, reglocs, \ + nitems, items); \ EXTRA_NOTES_IOPERM static const Ebl_Core_Item tls_items[] = diff --git a/backends/linux-core-note.c b/backends/linux-core-note.c index 7b1fc02..9d01219 100644 --- a/backends/linux-core-note.c +++ b/backends/linux-core-note.c @@ -1,5 +1,5 @@ /* Common core note type descriptions for Linux. - Copyright (C) 2007, 2008 Red Hat, Inc. + Copyright (C) 2007-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -23,6 +23,8 @@ Network licensing program, please visit www.openinventionnetwork.com . */ +#include + /* The including CPU_corenote.c file provides prstatus_regs and defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*. @@ -163,23 +165,61 @@ static const Ebl_Core_Item prpsinfo_items[] = FIELD (command, CHAR, psargs, 's', .count = PRARGSZ), }; +static const Ebl_Core_Item vmcoreinfo_items[] = + { + { + .type = ELF_T_BYTE, .format = '\n' + } + }; + #undef FIELD int -EBLHOOK(core_note) (n_type, descsz, - regs_offset, nregloc, reglocs, nitems, items) - GElf_Word n_type; - GElf_Word descsz; +EBLHOOK(core_note) (nhdr, name, regs_offset, nregloc, reglocs, nitems, items) + const GElf_Nhdr *nhdr; + const char *name; GElf_Word *regs_offset; size_t *nregloc; const Ebl_Register_Location **reglocs; size_t *nitems; const Ebl_Core_Item **items; { - switch (n_type) + switch (nhdr->n_namesz) + { + case sizeof "CORE" - 1: /* Buggy old Linux kernels. */ + if (memcmp (name, "CORE", nhdr->n_namesz) == 0) + break; + return 0; + + case sizeof "CORE": + if (memcmp (name, "CORE", nhdr->n_namesz) == 0) + break; + /* Buggy old Linux kernels didn't terminate "LINUX". + Fall through. */ + + case sizeof "LINUX": + if (memcmp (name, "LINUX", nhdr->n_namesz) == 0) + break; + return 0; + + case sizeof "VMCOREINFO": + if (nhdr->n_type != 0 + || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0) + return 0; + *regs_offset = 0; + *nregloc = 0; + *nitems = 1; + *items = vmcoreinfo_items; + return 1; + + default: + return 0; + } + + switch (nhdr->n_type) { case NT_PRSTATUS: - if (descsz != sizeof (struct EBLHOOK(prstatus))) + if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus))) return 0; *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg); *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0]; @@ -189,7 +229,7 @@ EBLHOOK(core_note) (n_type, descsz, return 1; case NT_PRPSINFO: - if (descsz != sizeof (struct EBLHOOK(prpsinfo))) + if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo))) return 0; *regs_offset = 0; *nregloc = 0; @@ -200,7 +240,7 @@ EBLHOOK(core_note) (n_type, descsz, #define EXTRA_REGSET(type, size, table) \ case type: \ - if (descsz != size) \ + if (nhdr->n_descsz != size) \ return 0; \ *regs_offset = 0; \ *nregloc = sizeof table / sizeof table[0]; \ diff --git a/backends/x86_corenote.c b/backends/x86_corenote.c index 7d55067..78849a6 100644 --- a/backends/x86_corenote.c +++ b/backends/x86_corenote.c @@ -1,5 +1,5 @@ /* x86-specific core note handling, pieces common to x86-64 and i386. - Copyright (C) 2005, 2008 Red Hat, Inc. + Copyright (C) 2005-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -25,7 +25,8 @@ #define EXTRA_NOTES_IOPERM \ case NT_386_IOPERM: \ - return ioperm_info (descsz, regs_offset, nregloc, reglocs, nitems, items); + return ioperm_info (nhdr->n_descsz, \ + regs_offset, nregloc, reglocs, nitems, items); static int ioperm_info (GElf_Word descsz, GElf_Word *regs_offset, diff --git a/libebl/ChangeLog b/libebl/ChangeLog index c4411e7..aaa1c86 100644 --- a/libebl/ChangeLog +++ b/libebl/ChangeLog @@ -1,3 +1,11 @@ +2010-01-04 Roland McGrath + + * eblcorenote.c (ebl_core_note): Take GElf_Nhdr * and name data + pointer instead of only n_type and n_descsz. + * libebl.h: Update declaration. + * ebl-hooks.h: Update core_note hook signature. + * eblopenbackend.c (default_core_note): Likewise. + 2009-10-14 Roland McGrath * eblobjnote.c (ebl_object_note): Clean up NT_GNU_GOLD_VERSION printing. diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h index d483f2a..59e73c5 100644 --- a/libebl/ebl-hooks.h +++ b/libebl/ebl-hooks.h @@ -1,5 +1,5 @@ /* Backend hook signatures internal interface for libebl. - Copyright (C) 2000-2009 Red Hat, Inc. + Copyright (C) 2000-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -114,8 +114,8 @@ const char *EBLHOOK(core_note_type_name) (uint32_t, char *, size_t); const char *EBLHOOK(object_note_type_name) (uint32_t, char *, size_t); /* Describe core note format. */ -int EBLHOOK(core_note) (GElf_Word, GElf_Word, GElf_Word *, size_t *, - const Ebl_Register_Location **, +int EBLHOOK(core_note) (const GElf_Nhdr *, const char *, + GElf_Word *, size_t *, const Ebl_Register_Location **, size_t *, const Ebl_Core_Item **); /* Handle object file note. */ diff --git a/libebl/eblcorenote.c b/libebl/eblcorenote.c index 553d5ba..7549ca6 100644 --- a/libebl/eblcorenote.c +++ b/libebl/eblcorenote.c @@ -1,5 +1,5 @@ /* Describe known core note formats. - Copyright (C) 2007 Red Hat, Inc. + Copyright (C) 2007, 2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -61,19 +61,19 @@ int -ebl_core_note (ebl, n_type, descsz, +ebl_core_note (ebl, nhdr, name, regs_offset, nregloc, reglocs, nitems, items) Ebl *ebl; - GElf_Word n_type; - GElf_Word descsz; + const GElf_Nhdr *nhdr; + const char *name; GElf_Word *regs_offset; size_t *nregloc; const Ebl_Register_Location **reglocs; size_t *nitems; const Ebl_Core_Item **items; { - int result = ebl->core_note (n_type, descsz, regs_offset, nregloc, reglocs, - nitems, items); + int result = ebl->core_note (nhdr, name, + regs_offset, nregloc, reglocs, nitems, items); if (result == 0) { /* The machine specific function did not know this type. */ @@ -81,7 +81,7 @@ ebl_core_note (ebl, n_type, descsz, *regs_offset = 0; *nregloc = 0; *reglocs = NULL; - switch (n_type) + switch (nhdr->n_type) { #define ITEMS(type, table) \ case type: \ diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c index b1bad90..edd8c4a 100644 --- a/libebl/eblopenbackend.c +++ b/libebl/eblopenbackend.c @@ -1,5 +1,5 @@ /* Generate ELF backend handle. - Copyright (C) 2000-2009 Red Hat, Inc. + Copyright (C) 2000-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -186,7 +186,7 @@ static const char *default_core_note_type_name (uint32_t, char *buf, size_t len); static const char *default_object_note_type_name (uint32_t, char *buf, size_t len); -static int default_core_note (GElf_Word n_type, GElf_Word descsz, +static int default_core_note (const GElf_Nhdr *nhdr, const char *name, GElf_Word *regs_offset, size_t *nregloc, const Ebl_Register_Location **reglocs, size_t *nitems, const Ebl_Core_Item **); @@ -604,8 +604,8 @@ default_auxv_info (GElf_Xword a_type __attribute__ ((unused)), } static int -default_core_note (GElf_Word n_type __attribute__ ((unused)), - GElf_Word descsz __attribute__ ((unused)), +default_core_note (const GElf_Nhdr *nhdr __attribute__ ((unused)), + const char *name __attribute__ ((unused)), GElf_Word *ro __attribute__ ((unused)), size_t *nregloc __attribute__ ((unused)), const Ebl_Register_Location **reglocs diff --git a/libebl/libebl.h b/libebl/libebl.h index 1a56b96..c94ad78 100644 --- a/libebl/libebl.h +++ b/libebl/libebl.h @@ -1,5 +1,5 @@ /* Interface for libebl. - Copyright (C) 2000, 2001-2009 Red Hat, Inc. + Copyright (C) 2000-2010 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -379,13 +379,13 @@ typedef struct bool thread_identifier; } Ebl_Core_Item; -/* Describe the format of a core file note with type field matching N_TYPE - and descriptor size matching DESCSZ. */ -extern int ebl_core_note (Ebl *ebl, GElf_Word n_type, GElf_Word descsz, +/* Describe the format of a core file note with the given header and NAME. + NAME is not guaranteed terminated, it's NHDR->n_namesz raw bytes. */ +extern int ebl_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const char *name, GElf_Word *regs_offset, size_t *nregloc, const Ebl_Register_Location **reglocs, size_t *nitems, const Ebl_Core_Item **items) - __nonnull_attribute__ (1, 4, 5, 6, 7, 8); + __nonnull_attribute__ (1, 2, 3, 4, 5, 6, 7, 8); /* Describe the auxv type number. */ extern int ebl_auxv_info (Ebl *ebl, GElf_Xword a_type, diff --git a/src/ChangeLog b/src/ChangeLog index c03f0b4..2e48a4e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,9 @@ 2010-01-04 Roland McGrath + * readelf.c (handle_notes_data): Grab NT_AUXV only for name "CORE". + (handle_core_note): Pass NHDR and NAME to ebl_core_note. + (handle_core_item): Handle .format of '\n' as \n-separated strings. + * readelf.c (implicit_debug_sections): New variable. (parse_opt): Set it instead of print_debug_sections for -a. OR them together for print_debug check. diff --git a/src/readelf.c b/src/readelf.c index ffd7ff4..2c263ec 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -6643,11 +6643,11 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, convsize = count * size; *repeated_size -= convsize; } - else + else if (item->count != 0 || item->format != '\n') *repeated_size -= size; } - desc = convert (core, item->type, count, data, desc + item->offset, convsize); + convert (core, item->type, count, data, desc + item->offset, convsize); Elf_Type type = item->type; if (type == ELF_T_ADDR) @@ -6793,6 +6793,33 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc, count, "%.*s", (int) count, value.Byte); break; + case '\n': + /* This is a list of strings separated by '\n'. */ + assert (item->count == 0); + assert (repeated_size != NULL); + assert (item->name == NULL); + if (unlikely (item->offset >= *repeated_size)) + break; + + const char *s = desc + item->offset; + size = *repeated_size - item->offset; + *repeated_size = 0; + while (size > 0) + { + const char *eol = memchr (s, '\n', size); + int len = size; + if (eol != NULL) + len = eol - s; + printf ("%*s%.*s\n", ITEM_INDENT, "", len, s); + if (eol == NULL) + break; + size -= eol + 1 - s; + s = eol + 1; + } + + colno = ITEM_WRAP_COLUMN; + break; + default: error (0, 0, "XXX not handling format '%c' for %s", item->format, item->name); @@ -7237,7 +7264,8 @@ handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos) } static void -handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const void *desc) +handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, + const char *name, const void *desc) { GElf_Word regs_offset; size_t nregloc; @@ -7245,7 +7273,7 @@ handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const void *desc) size_t nitems; const Ebl_Core_Item *items; - if (! ebl_core_note (ebl, nhdr->n_type, nhdr->n_descsz, + if (! ebl_core_note (ebl, nhdr, name, ®s_offset, &nregloc, ®locs, &nitems, &items)) return; @@ -7302,11 +7330,14 @@ handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr, { if (ehdr->e_type == ET_CORE) { - if (nhdr.n_type == NT_AUXV) + if (nhdr.n_type == NT_AUXV + && (nhdr.n_namesz == 4 /* Broken old Linux kernels. */ + || (nhdr.n_namesz == 5 && name[4] == '\0')) + && !memcmp (name, "CORE", 4)) handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz, start + desc_offset); else - handle_core_note (ebl, &nhdr, desc); + handle_core_note (ebl, &nhdr, name, desc); } else ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc); -- 2.7.4