From 1fdb08e5fc427b54b54214e3b3fbdda73d369f4d Mon Sep 17 00:00:00 2001 From: David Mosberger-Tang Date: Wed, 26 Jul 2006 22:36:03 -0600 Subject: [PATCH] Various fixes to get x86 to compile and work again. include/dwarf.h: Declare dwarf_reg_state_pool and dwarf_cie_info_pool. include/dwarf_i.h: Include libunwind_i.h instead of tdep.h. Make dwarf_to_unw_regnum() a macro so it doesn't get compiled into an object file merely because it include dwarf_i.h (important when optimization is turned off). (dwarf_read_encoded_pointer_inlined): New function. include/tdep-x86/libunwind_i.h: Add include of "mempool.h". include/tdep-x86_64/libunwind_i.h: Add include of "mempool.h". --- include/dwarf.h | 3 + include/dwarf_i.h | 147 ++++++++++++++++++++++++++++-- include/tdep-x86/libunwind_i.h | 1 + include/tdep-x86_64/libunwind_i.h | 1 + 4 files changed, 144 insertions(+), 8 deletions(-) diff --git a/include/dwarf.h b/include/dwarf.h index 1c6f776d..ac70c6bb 100644 --- a/include/dwarf.h +++ b/include/dwarf.h @@ -197,6 +197,9 @@ dwarf_cfa_t; #define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */ #define DW_EH_PE_aligned 0x50 /* aligned pointer */ +extern struct mempool dwarf_reg_state_pool; +extern struct mempool dwarf_cie_info_pool; + typedef enum { DWARF_WHERE_UNDEF, /* register isn't saved at all */ diff --git a/include/dwarf_i.h b/include/dwarf_i.h index 55320c2d..5b78dc04 100644 --- a/include/dwarf_i.h +++ b/include/dwarf_i.h @@ -7,19 +7,15 @@ files are compiled with inlining disabled. */ #include "dwarf.h" -#include "tdep.h" +#include "libunwind_i.h" #define dwarf_to_unw_regnum_map UNW_OBJ (dwarf_to_unw_regnum_map) extern uint8_t dwarf_to_unw_regnum_map[DWARF_REGNUM_MAP_LENGTH]; -static inline unw_regnum_t -dwarf_to_unw_regnum (unw_word_t regnum) -{ - if (regnum <= DWARF_REGNUM_MAP_LENGTH) - return dwarf_to_unw_regnum_map[regnum]; - return 0; -} +/* REG is evaluated multiple times; it better be side-effects free! */ +#define dwarf_to_unw_regnum(reg) \ + (((reg) <= DWARF_REGNUM_MAP_LENGTH) ? dwarf_to_unw_regnum_map[reg] : 0) #ifdef UNW_LOCAL_ONLY @@ -340,4 +336,139 @@ dwarf_read_sleb128 (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr, return 0; } +static ALWAYS_INLINE int +dwarf_read_encoded_pointer_inlined (unw_addr_space_t as, unw_accessors_t *a, + unw_word_t *addr, unsigned char encoding, + const unw_proc_info_t *pi, + unw_word_t *valp, void *arg) +{ + unw_word_t val, initial_addr = *addr; + uint16_t uval16; + uint32_t uval32; + uint64_t uval64; + int16_t sval16; + int32_t sval32; + int64_t sval64; + int ret; + + /* DW_EH_PE_omit and DW_EH_PE_aligned don't follow the normal + format/application encoding. Handle them first. */ + if (encoding == DW_EH_PE_omit) + { + *valp = 0; + return 0; + } + else if (encoding == DW_EH_PE_aligned) + { + *addr = (initial_addr + sizeof (unw_word_t) - 1) & -sizeof (unw_word_t); + return dwarf_readw (as, a, addr, valp, arg); + } + + switch (encoding & DW_EH_PE_FORMAT_MASK) + { + case DW_EH_PE_ptr: + if ((ret = dwarf_readw (as, a, addr, &val, arg)) < 0) + return ret; + break; + + case DW_EH_PE_uleb128: + if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) + return ret; + break; + + case DW_EH_PE_udata2: + if ((ret = dwarf_readu16 (as, a, addr, &uval16, arg)) < 0) + return ret; + val = uval16; + break; + + case DW_EH_PE_udata4: + if ((ret = dwarf_readu32 (as, a, addr, &uval32, arg)) < 0) + return ret; + val = uval32; + break; + + case DW_EH_PE_udata8: + if ((ret = dwarf_readu64 (as, a, addr, &uval64, arg)) < 0) + return ret; + val = uval64; + break; + + case DW_EH_PE_sleb128: + if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0) + return ret; + break; + + case DW_EH_PE_sdata2: + if ((ret = dwarf_reads16 (as, a, addr, &sval16, arg)) < 0) + return ret; + val = sval16; + break; + + case DW_EH_PE_sdata4: + if ((ret = dwarf_reads32 (as, a, addr, &sval32, arg)) < 0) + return ret; + val = sval32; + break; + + case DW_EH_PE_sdata8: + if ((ret = dwarf_reads64 (as, a, addr, &sval64, arg)) < 0) + return ret; + val = sval64; + break; + + default: + Debug (1, "unexpected encoding format 0x%x\n", + encoding & DW_EH_PE_FORMAT_MASK); + return -UNW_EINVAL; + } + + if (val == 0) + { + /* 0 is a special value and always absolute. */ + *valp = 0; + return 0; + } + + switch (encoding & DW_EH_PE_APPL_MASK) + { + case DW_EH_PE_absptr: + break; + + case DW_EH_PE_pcrel: + val += initial_addr; + break; + + case DW_EH_PE_datarel: + /* XXX For now, assume that data-relative addresses are relative + to the global pointer. */ + val += pi->gp; + break; + + case DW_EH_PE_funcrel: + val += pi->start_ip; + break; + + case DW_EH_PE_textrel: + /* XXX For now we don't support text-rel values. If there is a + platform which needs this, we probably would have to add a + "segbase" member to unw_proc_info_t. */ + default: + Debug (1, "unexpected application type 0x%x\n", + encoding & DW_EH_PE_APPL_MASK); + return -UNW_EINVAL; + } + + if (encoding & DW_EH_PE_indirect) + { + unw_word_t indirect_addr = val; + + if ((ret = dwarf_readw (as, a, &indirect_addr, &val, arg)) < 0) + return ret; + } + + *valp = val; + return 0; +} + #endif /* DWARF_I_H */ diff --git a/include/tdep-x86/libunwind_i.h b/include/tdep-x86/libunwind_i.h index 740aef74..1a43882a 100644 --- a/include/tdep-x86/libunwind_i.h +++ b/include/tdep-x86/libunwind_i.h @@ -33,6 +33,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "elf32.h" +#include "mempool.h" #include "dwarf.h" struct unw_addr_space diff --git a/include/tdep-x86_64/libunwind_i.h b/include/tdep-x86_64/libunwind_i.h index 9984febb..e351452a 100644 --- a/include/tdep-x86_64/libunwind_i.h +++ b/include/tdep-x86_64/libunwind_i.h @@ -35,6 +35,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "elf64.h" +#include "mempool.h" #include "dwarf.h" struct unw_addr_space