summaryrefslogtreecommitdiffstats
path: root/src/readelf.c
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2010-02-23 15:34:37 -0800
committerRoland McGrath <[email protected]>2010-02-23 15:35:43 -0800
commit69556fcf845e9482e76c4817cce9902b8ab0f492 (patch)
tree9526a9ea05e182636f37015d046fc6ae2afb7538 /src/readelf.c
parent3eb92e40855f3179d8f05d333bc42c76bae747a8 (diff)
parentbc87bd74a6ecf7d8559c83c8047f5ed11e93f1fe (diff)
Merge commit 'origin/master' into dwarf
Conflicts: libdw/Makefile.am
Diffstat (limited to 'src/readelf.c')
-rw-r--r--src/readelf.c59
1 files changed, 21 insertions, 38 deletions
diff --git a/src/readelf.c b/src/readelf.c
index c3380a5f..22d6521a 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -49,6 +49,7 @@
#include <time.h>
#include <unistd.h>
#include <sys/param.h>
+#include <sys/stat.h>
#include <system.h>
#include "../libelf/libelfP.h"
@@ -4112,8 +4113,7 @@ print_encoding_base (const char *pfx, unsigned int fde_encoding)
{
unsigned int w = fde_encoding;
- if (w & 0xf)
- w = print_encoding (w);
+ w = print_encoding (w);
if (w & 0x70)
{
@@ -4135,6 +4135,10 @@ static const unsigned char *
read_encoded (unsigned int encoding, const unsigned char *readp,
const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
{
+ if ((encoding & 0xf) == DW_EH_PE_absptr)
+ encoding = gelf_getclass (dbg->elf) == ELFCLASS32
+ ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
+
switch (encoding & 0xf)
{
case DW_EH_PE_uleb128:
@@ -4322,6 +4326,9 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
unsigned int augmentationlen;
get_uleb128 (augmentationlen, readp);
+ if (augmentationlen > (size_t) (dataend - readp))
+ error (1, 0, gettext ("invalid augmentation length"));
+
const char *hdr = "Augmentation data:";
const char *cp = augmentation + 1;
while (*cp != '\0')
@@ -4348,51 +4355,27 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
const unsigned char *startp = readp;
unsigned int encoding = *readp++;
uint64_t val = 0;
- int64_t sval = 0;
- bool is_signed = false;
+ readp = read_encoded (encoding, readp,
+ readp - 1 + augmentationlen,
+ &val, dbg);
+
+ while (++startp < readp)
+ printf ("%#x ", *startp);
+ putchar ('(');
+ print_encoding (encoding);
+ putchar (' ');
switch (encoding & 0xf)
{
- case DW_EH_PE_uleb128:
- get_uleb128 (val, readp);
- break;
case DW_EH_PE_sleb128:
- get_sleb128 (sval, readp);
- is_signed = true;
- break;
- case DW_EH_PE_udata2:
- val = read_2ubyte_unaligned_inc (dbg, readp);
- break;
- case DW_EH_PE_udata4:
- val = read_4ubyte_unaligned_inc (dbg, readp);
- break;
- case DW_EH_PE_udata8:
- val = read_8ubyte_unaligned_inc (dbg, readp);
- break;
case DW_EH_PE_sdata2:
- val = read_2sbyte_unaligned_inc (dbg, readp);
- is_signed = true;
- break;
case DW_EH_PE_sdata4:
- val = read_4sbyte_unaligned_inc (dbg, readp);
- is_signed = true;
- break;
- case DW_EH_PE_sdata8:
- val = read_8sbyte_unaligned_inc (dbg, readp);
- is_signed = true;
+ printf ("%" PRId64 ")\n", val);
break;
default:
- error (1, 0,
- gettext ("invalid augmentation encoding"));
+ printf ("%#" PRIx64 ")\n", val);
+ break;
}
-
- while (++startp < readp)
- printf ("%#x ", *startp);
-
- if (is_signed)
- printf ("(%" PRId64 ")\n", sval);
- else
- printf ("(%" PRIu64 ")\n", val);
}
else
printf ("(%x)\n", *readp++);