Juan Cespedes | 1cd999a | 2001-07-03 00:46:04 +0200 | [diff] [blame] | 1 | #ifndef LTRACE_ELF_H |
| 2 | #define LTRACE_ELF_H |
| 3 | |
Juan Cespedes | d914a20 | 2004-11-10 00:15:33 +0100 | [diff] [blame] | 4 | #include <gelf.h> |
| 5 | #include <stdlib.h> |
| 6 | |
Petr Machata | e67635d | 2012-03-21 03:37:39 +0100 | [diff] [blame^] | 7 | #define DEFINING_LTELF |
| 8 | #include "arch.h" |
| 9 | #undef DEFINING_LTELF |
| 10 | |
| 11 | #ifndef ARCH_HAVE_LTELF_DATA |
| 12 | struct arch_ltelf_data { |
| 13 | }; |
| 14 | #endif |
| 15 | |
Petr Machata | 2b46cfc | 2012-02-18 11:17:29 +0100 | [diff] [blame] | 16 | struct Process; |
| 17 | struct library; |
| 18 | |
| 19 | /* XXX Ok, the original idea was to separate the low-level ELF data |
| 20 | * from the abstract "struct library" object, but we use some of the |
| 21 | * following extensively in the back end. Not all though. So what we |
| 22 | * use should be move to struct library, and the rest of this |
| 23 | * structure maybe could be safely hidden in .c. How to integrate the |
| 24 | * arch-specific bits into struct library is unclear as of now. */ |
Ian Wienand | 2d45b1a | 2006-02-20 22:48:07 +0100 | [diff] [blame] | 25 | struct ltelf { |
| 26 | int fd; |
| 27 | Elf *elf; |
| 28 | GElf_Ehdr ehdr; |
| 29 | Elf_Data *dynsym; |
| 30 | size_t dynsym_count; |
| 31 | const char *dynstr; |
| 32 | GElf_Addr plt_addr; |
| 33 | size_t plt_size; |
| 34 | Elf_Data *relplt; |
Petr Machata | e67635d | 2012-03-21 03:37:39 +0100 | [diff] [blame^] | 35 | Elf_Data *plt_data; |
Ian Wienand | 2d45b1a | 2006-02-20 22:48:07 +0100 | [diff] [blame] | 36 | size_t relplt_count; |
| 37 | Elf_Data *symtab; |
| 38 | const char *strtab; |
Petr Machata | 2b46cfc | 2012-02-18 11:17:29 +0100 | [diff] [blame] | 39 | const char *soname; |
Ian Wienand | 2d45b1a | 2006-02-20 22:48:07 +0100 | [diff] [blame] | 40 | size_t symtab_count; |
| 41 | Elf_Data *opd; |
| 42 | GElf_Addr *opd_addr; |
| 43 | size_t opd_size; |
Paul Gilliam | 76c61f1 | 2006-06-14 06:55:21 +0200 | [diff] [blame] | 44 | int lte_flags; |
Joe Damato | 87f4f58 | 2010-11-08 15:47:36 -0800 | [diff] [blame] | 45 | GElf_Addr dyn_addr; |
| 46 | size_t dyn_sz; |
Petr Machata | e67635d | 2012-03-21 03:37:39 +0100 | [diff] [blame^] | 47 | size_t relplt_size; |
Petr Machata | 29add4f | 2012-02-18 16:38:05 +0100 | [diff] [blame] | 48 | GElf_Addr bias; |
Petr Machata | 2b46cfc | 2012-02-18 11:17:29 +0100 | [diff] [blame] | 49 | GElf_Addr entry_addr; |
Petr Machata | 29add4f | 2012-02-18 16:38:05 +0100 | [diff] [blame] | 50 | GElf_Addr base_addr; |
Petr Machata | e67635d | 2012-03-21 03:37:39 +0100 | [diff] [blame^] | 51 | struct arch_ltelf_data arch; |
Juan Cespedes | 1cd999a | 2001-07-03 00:46:04 +0200 | [diff] [blame] | 52 | }; |
| 53 | |
Joe Damato | 47cae1e | 2010-11-08 15:47:39 -0800 | [diff] [blame] | 54 | #define ELF_MAX_SEGMENTS 50 |
Paul Gilliam | 76c61f1 | 2006-06-14 06:55:21 +0200 | [diff] [blame] | 55 | #define LTE_PLT_EXECUTABLE 2 |
| 56 | |
Petr Machata | 2b46cfc | 2012-02-18 11:17:29 +0100 | [diff] [blame] | 57 | #define PLTS_ARE_EXECUTABLE(lte) (((lte)->lte_flags & LTE_PLT_EXECUTABLE) != 0) |
Paul Gilliam | 76c61f1 | 2006-06-14 06:55:21 +0200 | [diff] [blame] | 58 | |
Petr Machata | 2b46cfc | 2012-02-18 11:17:29 +0100 | [diff] [blame] | 59 | int open_elf(struct ltelf *lte, const char *filename); |
Juan Cespedes | 1cd999a | 2001-07-03 00:46:04 +0200 | [diff] [blame] | 60 | |
Petr Machata | 2b46cfc | 2012-02-18 11:17:29 +0100 | [diff] [blame] | 61 | /* XXX is it possible to put breakpoints in VDSO and VSYSCALL |
| 62 | * pseudo-libraries? For now we assume that all libraries can be |
| 63 | * opened via a filesystem. BASE is ignored for ET_EXEC files. */ |
| 64 | struct library *ltelf_read_library(const char *filename, GElf_Addr base); |
Juan Cespedes | d914a20 | 2004-11-10 00:15:33 +0100 | [diff] [blame] | 65 | |
Petr Machata | 2b46cfc | 2012-02-18 11:17:29 +0100 | [diff] [blame] | 66 | /* Create a library object representing the main binary. The entry |
| 67 | * point address is stored to *ENTRYP. */ |
| 68 | struct library *ltelf_read_main_binary(struct Process *proc, const char *path); |
Juan Cespedes | 96935a9 | 1997-08-09 23:45:39 +0200 | [diff] [blame] | 69 | |
Petr Machata | 2b46cfc | 2012-02-18 11:17:29 +0100 | [diff] [blame] | 70 | GElf_Addr arch_plt_sym_val(struct ltelf *, size_t, GElf_Rela *); |
Zachary T Welch | 3ba522f | 2010-12-14 15:12:47 -0800 | [diff] [blame] | 71 | |
Petr Machata | e67635d | 2012-03-21 03:37:39 +0100 | [diff] [blame^] | 72 | Elf_Data *elf_loaddata(Elf_Scn *scn, GElf_Shdr *shdr); |
| 73 | int elf_get_section_covering(struct ltelf *lte, GElf_Addr addr, |
| 74 | Elf_Scn **tgt_sec, GElf_Shdr *tgt_shdr); |
| 75 | |
| 76 | /* Read, respectively, 2, 4, or 8 bytes from Elf data at given OFFSET, |
| 77 | * and store it in *RETP. Returns 0 on success or a negative value if |
| 78 | * there's not enough data. */ |
| 79 | int elf_read_u16(Elf_Data *data, size_t offset, uint16_t *retp); |
| 80 | int elf_read_u32(Elf_Data *data, size_t offset, uint32_t *retp); |
| 81 | int elf_read_u64(Elf_Data *data, size_t offset, uint64_t *retp); |
| 82 | |
| 83 | |
Zachary T Welch | 3ba522f | 2010-12-14 15:12:47 -0800 | [diff] [blame] | 84 | #if __WORDSIZE == 32 |
| 85 | #define PRI_ELF_ADDR PRIx32 |
| 86 | #define GELF_ADDR_CAST(x) (void *)(uint32_t)(x) |
| 87 | #else |
| 88 | #define PRI_ELF_ADDR PRIx64 |
| 89 | #define GELF_ADDR_CAST(x) (void *)(x) |
| 90 | #endif |
| 91 | |
Juan Cespedes | 1cd999a | 2001-07-03 00:46:04 +0200 | [diff] [blame] | 92 | #endif |