summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2009-01-27 17:08:03 -0800
committerRoland McGrath <[email protected]>2009-01-27 17:08:03 -0800
commit51f01285dca04c78350d75bb62bba1350a05e252 (patch)
tree014b445e574ec9fb9ad6fa3c10ac33e747fb0017
parente738ad2e9f2b5a95dfd86f986ee3ebc0fc41f46c (diff)
readelf .debug_loc robustness fixes.
-rw-r--r--src/ChangeLog9
-rw-r--r--src/readelf.c52
2 files changed, 55 insertions, 6 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 4886bcf2..af4e61ec 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,12 @@
+2009-01-27 Roland McGrath <[email protected]>
+
+ * readelf.c (print_ops): Notice short length, don't overrun buffer
+ (still need to fix LEB128).
+
+ * readelf.c (print_ops): Fix DW_OP_call[24] decoding.
+
+ * readelf.c (print_ops): Print (empty)\n when LEN == 0.
+
2009-01-24 Ulrich Drepper <[email protected]>
* readelf.c (print_debug_frame_section): Fix computation of vma_base
diff --git a/src/readelf.c b/src/readelf.c
index 55c906f7..1f7faf79 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3785,6 +3785,14 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
[DW_OP_bit_piece] = "bit_piece",
};
+ if (len == 0)
+ {
+ printf ("%*s(empty)\n", indent, "");
+ return;
+ }
+
+#define NEED(n) if (len < n) goto invalid;
+
Dwarf_Word offset = 0;
while (len-- > 0)
{
@@ -3796,6 +3804,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
case DW_OP_addr:;
/* Address operand. */
Dwarf_Word addr;
+ NEED (addrsize);
if (addrsize == 4)
addr = read_4ubyte_unaligned (dbg, data);
else
@@ -3825,6 +3834,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
case DW_OP_pick:
case DW_OP_const1u:
// XXX value might be modified by relocation
+ NEED (1);
printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 "\n",
indent, "", (uintmax_t) offset,
known[op], *((uint8_t *) data));
@@ -3834,6 +3844,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
break;
case DW_OP_const2u:
+ NEED (2);
// XXX value might be modified by relocation
printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
indent, "", (uintmax_t) offset,
@@ -3844,6 +3855,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
break;
case DW_OP_const4u:
+ NEED (4);
// XXX value might be modified by relocation
printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
indent, "", (uintmax_t) offset,
@@ -3854,6 +3866,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
break;
case DW_OP_const8u:
+ NEED (8);
// XXX value might be modified by relocation
printf ("%*s[%4" PRIuMAX "] %s %" PRIu64 "\n",
indent, "", (uintmax_t) offset,
@@ -3864,6 +3877,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
break;
case DW_OP_const1s:
+ NEED (1);
// XXX value might be modified by relocation
printf ("%*s[%4" PRIuMAX "] %s %" PRId8 "\n",
indent, "", (uintmax_t) offset,
@@ -3874,6 +3888,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
break;
case DW_OP_const2s:
+ NEED (2);
// XXX value might be modified by relocation
printf ("%*s[%4" PRIuMAX "] %s %" PRId16 "\n",
indent, "", (uintmax_t) offset,
@@ -3884,6 +3899,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
break;
case DW_OP_const4s:
+ NEED (4);
// XXX value might be modified by relocation
printf ("%*s[%4" PRIuMAX "] %s %" PRId32 "\n",
indent, "", (uintmax_t) offset,
@@ -3894,6 +3910,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
break;
case DW_OP_const8s:
+ NEED (8);
// XXX value might be modified by relocation
printf ("%*s[%4" PRIuMAX "] %s %" PRId64 "\n",
indent, "", (uintmax_t) offset,
@@ -3909,7 +3926,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
case DW_OP_constu:;
const unsigned char *start = data;
unsigned int uleb;
- get_uleb128 (uleb, data);
+ get_uleb128 (uleb, data); /* XXX check overrun */
printf ("%*s[%4" PRIuMAX "] %s %u\n",
indent, "", (uintmax_t) offset, known[op], uleb);
len -= data - start;
@@ -3919,8 +3936,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
case DW_OP_bit_piece:
start = data;
unsigned int uleb2;
- get_uleb128 (uleb, data);
- get_uleb128 (uleb2, data);
+ get_uleb128 (uleb, data); /* XXX check overrun */
+ get_uleb128 (uleb2, data); /* XXX check overrun */
printf ("%*s[%4" PRIuMAX "] %s %u, %u\n",
indent, "", (uintmax_t) offset, known[op], uleb, uleb2);
len -= data - start;
@@ -3932,7 +3949,7 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
case DW_OP_consts:
start = data;
unsigned int sleb;
- get_sleb128 (sleb, data);
+ get_sleb128 (sleb, data); /* XXX check overrun */
printf ("%*s[%4" PRIuMAX "] %s %d\n",
indent, "", (uintmax_t) offset, known[op], sleb);
len -= data - start;
@@ -3941,8 +3958,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
case DW_OP_bregx:
start = data;
- get_uleb128 (uleb, data);
- get_sleb128 (sleb, data);
+ get_uleb128 (uleb, data); /* XXX check overrun */
+ get_sleb128 (sleb, data); /* XXX check overrun */
printf ("%*s[%4" PRIuMAX "] %s %u %d\n",
indent, "", (uintmax_t) offset, known[op], uleb, sleb);
len -= data - start;
@@ -3950,9 +3967,26 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
break;
case DW_OP_call2:
+ NEED (2);
+ printf ("%*s[%4" PRIuMAX "] %s %" PRIu16 "\n",
+ indent, "", (uintmax_t) offset, known[op],
+ read_2ubyte_unaligned (dbg, data));
+ len -= 2;
+ offset += 3;
+ break;
+
case DW_OP_call4:
+ NEED (4);
+ printf ("%*s[%4" PRIuMAX "] %s %" PRIu32 "\n",
+ indent, "", (uintmax_t) offset, known[op],
+ read_4ubyte_unaligned (dbg, data));
+ len -= 4;
+ offset += 5;
+ break;
+
case DW_OP_skip:
case DW_OP_bra:
+ NEED (2);
printf ("%*s[%4" PRIuMAX "] %s %" PRIuMAX "\n",
indent, "", (uintmax_t) offset, known[op],
(uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
@@ -3974,6 +4008,12 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
}
indent = indentrest;
+ continue;
+
+ invalid:
+ printf (gettext ("%*s[%4" PRIuMAX "] %s <TRUNCATED>\n"),
+ indent, "", (uintmax_t) offset, known[op]);
+ break;
}
}