mirror of
https://github.com/davea42/libdwarf-code.git
synced 2025-10-23 10:27:48 +08:00
standard tables: header says lno now, for line number (row was incorrect). dwarfdump/dwarfdump.c dwarfdump/print_die.c dwarfdump/print_lines.c New checks for correctness and section overrun. Fixed duplicate free due to bug in DWARF5 macro handling. libdwarf/dwarf_arange.c libdwarf/dwarf_die_deliv.c libdwarf/dwarf_elf_access.c libdwarf/dwarf_errmsg_list.c libdwarf/dwarf_frame2.c libdwarf/dwarf_leb.c libdwarf/dwarf_line.c libdwarf/dwarf_line.h libdwarf/dwarf_line_table_reader_common.c libdwarf/dwarf_macro5.c libdwarf/dwarf_util.h libdwarf/libdwarf.h.in
300 lines
8.7 KiB
C
300 lines
8.7 KiB
C
/*
|
|
|
|
Copyright (C) 2000,2004 Silicon Graphics, Inc. All Rights Reserved.
|
|
Portions Copyright 2011 David Anderson. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of version 2.1 of the GNU Lesser General Public License
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it would be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
Further, this software is distributed without any warranty that it is
|
|
free of the rightful claim of any third person regarding infringement
|
|
or the like. Any license provided herein, whether implied or
|
|
otherwise, applies only to this software file. Patent licenses, if
|
|
any, provided herein do not apply to combinations of this program with
|
|
other software, or any other product whatsoever.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this program; if not, write the Free Software
|
|
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
|
|
USA.
|
|
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "dwarf_incl.h"
|
|
#include <stdio.h>
|
|
|
|
/* 10 bytes of leb, 7 bits each part of the number, gives
|
|
room for a 64bit number.
|
|
While any number of leading zeroes would be legal, so
|
|
no max is really truly required here, why would a
|
|
compiler generate leading zeros? That would
|
|
be strange.
|
|
*/
|
|
#define BYTESLEBMAX 10
|
|
|
|
|
|
/* Decode ULEB */
|
|
Dwarf_Unsigned
|
|
_dwarf_decode_u_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length)
|
|
{
|
|
unsigned char byte = 0;
|
|
Dwarf_Word word_number = 0;
|
|
Dwarf_Unsigned number = 0;
|
|
Dwarf_Sword shift = 0;
|
|
/* The byte_length value will be a small non-negative integer. */
|
|
unsigned byte_length = 0;
|
|
|
|
/* The following unrolls-the-loop for the first few bytes and
|
|
unpacks into 32 bits to make this as fast as possible.
|
|
word_number is assumed big enough that the shift has a defined
|
|
result. */
|
|
if ((*leb128 & 0x80) == 0) {
|
|
if (leb128_length) {
|
|
*leb128_length = 1;
|
|
}
|
|
return (*leb128);
|
|
} else if ((*(leb128 + 1) & 0x80) == 0) {
|
|
if (leb128_length) {
|
|
*leb128_length = 2;
|
|
}
|
|
word_number = *leb128 & 0x7f;
|
|
word_number |= (*(leb128 + 1) & 0x7f) << 7;
|
|
return (word_number);
|
|
} else if ((*(leb128 + 2) & 0x80) == 0) {
|
|
if (leb128_length) {
|
|
*leb128_length = 3;
|
|
}
|
|
word_number = *leb128 & 0x7f;
|
|
word_number |= (*(leb128 + 1) & 0x7f) << 7;
|
|
word_number |= (*(leb128 + 2) & 0x7f) << 14;
|
|
return (word_number);
|
|
} else if ((*(leb128 + 3) & 0x80) == 0) {
|
|
if (leb128_length) {
|
|
*leb128_length = 4;
|
|
}
|
|
word_number = *leb128 & 0x7f;
|
|
word_number |= (*(leb128 + 1) & 0x7f) << 7;
|
|
word_number |= (*(leb128 + 2) & 0x7f) << 14;
|
|
word_number |= (*(leb128 + 3) & 0x7f) << 21;
|
|
return (word_number);
|
|
}
|
|
|
|
/* The rest handles long numbers Because the 'number' may be larger
|
|
than the default int/unsigned, we must cast the 'byte' before
|
|
the shift for the shift to have a defined result. */
|
|
number = 0;
|
|
shift = 0;
|
|
byte_length = 1;
|
|
byte = *leb128;
|
|
for (;;) {
|
|
number |= ((Dwarf_Unsigned) (byte & 0x7f)) << shift;
|
|
|
|
if ((byte & 0x80) == 0) {
|
|
if (leb128_length) {
|
|
*leb128_length = byte_length;
|
|
}
|
|
return (number);
|
|
}
|
|
shift += 7;
|
|
|
|
byte_length++;
|
|
if (byte_length > BYTESLEBMAX) {
|
|
/* Erroneous input. What to do?
|
|
Abort? Return error? Just stop here?
|
|
Call _dwarf_decode_u_leb128_chk instead. */
|
|
if( leb128_length) {
|
|
*leb128_length = BYTESLEBMAX;
|
|
}
|
|
return number;
|
|
}
|
|
++leb128;
|
|
byte = *leb128;
|
|
}
|
|
}
|
|
|
|
/* Decode ULEB with checking */
|
|
int
|
|
_dwarf_decode_u_leb128_chk(Dwarf_Small * leb128, Dwarf_Word * leb128_length,
|
|
Dwarf_Unsigned *outval,Dwarf_Byte_Ptr endptr)
|
|
{
|
|
unsigned char byte = 0;
|
|
Dwarf_Word word_number = 0;
|
|
Dwarf_Unsigned number = 0;
|
|
Dwarf_Sword shift = 0;
|
|
/* The byte_length value will be a small non-negative integer. */
|
|
unsigned byte_length = 0;
|
|
|
|
if (leb128 >=endptr) {
|
|
return DW_DLV_ERROR;
|
|
}
|
|
/* The following unrolls-the-loop for the first two bytes and
|
|
unpacks into 32 bits to make this as fast as possible.
|
|
word_number is assumed big enough that the shift has a defined
|
|
result. */
|
|
if ((*leb128 & 0x80) == 0) {
|
|
if (leb128_length) {
|
|
*leb128_length = 1;
|
|
}
|
|
*outval = *leb128;
|
|
return DW_DLV_OK;
|
|
} else {
|
|
if ((leb128+1) >=endptr) {
|
|
return DW_DLV_ERROR;
|
|
}
|
|
if ((*(leb128 + 1) & 0x80) == 0) {
|
|
if (leb128_length) {
|
|
*leb128_length = 2;
|
|
}
|
|
word_number = *leb128 & 0x7f;
|
|
word_number |= (*(leb128 + 1) & 0x7f) << 7;
|
|
*outval = word_number;
|
|
return DW_DLV_OK;
|
|
}
|
|
/* Gets messy to hand-inline more byte checking. */
|
|
}
|
|
|
|
/* The rest handles long numbers Because the 'number' may be larger
|
|
than the default int/unsigned, we must cast the 'byte' before
|
|
the shift for the shift to have a defined result. */
|
|
number = 0;
|
|
shift = 0;
|
|
byte_length = 1;
|
|
byte = *leb128;
|
|
for (;;) {
|
|
number |= ((Dwarf_Unsigned) (byte & 0x7f)) << shift;
|
|
|
|
if ((byte & 0x80) == 0) {
|
|
if (leb128_length) {
|
|
*leb128_length = byte_length;
|
|
}
|
|
*outval = number;
|
|
return DW_DLV_OK;
|
|
}
|
|
shift += 7;
|
|
|
|
byte_length++;
|
|
if (byte_length > BYTESLEBMAX) {
|
|
/* Erroneous input. */
|
|
if( leb128_length) {
|
|
*leb128_length = BYTESLEBMAX;
|
|
}
|
|
break;
|
|
}
|
|
++leb128;
|
|
if ((leb128) >=endptr) {
|
|
return DW_DLV_ERROR;
|
|
}
|
|
byte = *leb128;
|
|
}
|
|
return DW_DLV_ERROR;
|
|
}
|
|
|
|
|
|
#define BITSINBYTE 8
|
|
|
|
/* decode SLEB */
|
|
Dwarf_Signed
|
|
_dwarf_decode_s_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length)
|
|
{
|
|
Dwarf_Signed number = 0;
|
|
Dwarf_Bool sign = 0;
|
|
Dwarf_Word shift = 0;
|
|
unsigned char byte = *leb128;
|
|
/* The byte_length value will be a small non-negative integer. */
|
|
unsigned byte_length = 1;
|
|
|
|
/* byte_length being the number of bytes of data absorbed so far in
|
|
turning the leb into a Dwarf_Signed. */
|
|
for (;;) {
|
|
sign = byte & 0x40;
|
|
number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift;
|
|
shift += 7;
|
|
|
|
if ((byte & 0x80) == 0) {
|
|
break;
|
|
}
|
|
++leb128;
|
|
byte = *leb128;
|
|
byte_length++;
|
|
if (byte_length > BYTESLEBMAX) {
|
|
/* Erroneous input, as who would put leading
|
|
0x80 for leading zeros?
|
|
call _dwarf_decode_s_leb128_chk instead. */
|
|
if (leb128_length) {
|
|
*leb128_length = BYTESLEBMAX;
|
|
}
|
|
return number;
|
|
}
|
|
}
|
|
|
|
if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) {
|
|
number |= -((Dwarf_Signed) 1 << shift);
|
|
}
|
|
|
|
if (leb128_length) {
|
|
*leb128_length = byte_length;
|
|
}
|
|
return number;
|
|
}
|
|
|
|
int
|
|
_dwarf_decode_s_leb128_chk(Dwarf_Small * leb128, Dwarf_Word * leb128_length,
|
|
Dwarf_Signed *outval,Dwarf_Byte_Ptr endptr)
|
|
{
|
|
Dwarf_Signed number = 0;
|
|
Dwarf_Bool sign = 0;
|
|
Dwarf_Word shift = 0;
|
|
unsigned char byte = 0;
|
|
/* The byte_length value will be a small non-negative integer. */
|
|
unsigned byte_length = 1;
|
|
|
|
/* byte_length being the number of bytes of data absorbed so far in
|
|
turning the leb into a Dwarf_Signed. */
|
|
if (!outval) {
|
|
return DW_DLV_ERROR;
|
|
}
|
|
if (leb128 >= endptr) {
|
|
return DW_DLV_ERROR;
|
|
}
|
|
byte = *leb128;
|
|
for (;;) {
|
|
sign = byte & 0x40;
|
|
number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift;
|
|
shift += 7;
|
|
|
|
if ((byte & 0x80) == 0) {
|
|
break;
|
|
}
|
|
++leb128;
|
|
byte = *leb128;
|
|
byte_length++;
|
|
if (leb128 >= endptr) {
|
|
return DW_DLV_ERROR;
|
|
}
|
|
if (byte_length > BYTESLEBMAX) {
|
|
/* Erroneous input. */
|
|
if (leb128_length) {
|
|
*leb128_length = BYTESLEBMAX;
|
|
}
|
|
return DW_DLV_ERROR;
|
|
}
|
|
}
|
|
|
|
if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) {
|
|
number |= -((Dwarf_Signed) 1 << shift);
|
|
}
|
|
|
|
if (leb128_length) {
|
|
*leb128_length = byte_length;
|
|
}
|
|
*outval = number;
|
|
return DW_DLV_OK;
|
|
}
|
|
|