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