Advertisement
TheRouletteBoi

readelf sections and symbols

Oct 15th, 2018
1,278
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 45.98 KB | None | 0 0
  1. // read ELF
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8. /*
  9. * Data Representation
  10. */
  11.  
  12.  
  13. /* 32-bit Data Types */
  14. typedef uint32_t    Elf32_Addr;
  15. typedef uint32_t    Elf32_Off;
  16. typedef uint16_t    Elf32_Half;
  17. typedef uint32_t    Elf32_Word;
  18. typedef int32_t     Elf32_Sword;
  19.  
  20. /* 64-bit Data Types */
  21. typedef uint64_t    Elf64_Addr;
  22. typedef uint64_t    Elf64_Off;
  23. typedef uint16_t    Elf64_Half;
  24. typedef uint32_t    Elf64_Word;
  25. typedef int32_t     Elf64_Sword;
  26. typedef uint64_t    Elf64_Xword;
  27. typedef uint64_t    Elf64_Sxword;
  28.  
  29. /*
  30. * ELF header
  31. */
  32.  
  33. /* e_ident[] Identification Indexes */
  34. #define EI_MAG0     0   /* File identification */
  35. #define EI_MAG1     1   /* File identification */
  36. #define EI_MAG2     2   /* File identification */
  37. #define EI_MAG3     3   /* File identification */
  38. #define EI_CLASS    4   /* File class */
  39. #define EI_DATA     5   /* Data encoding */
  40. #define EI_VERSION  6   /* File version */
  41. #define EI_OSABI    7   /* Operating system/ABI identification */
  42. #define EI_ABIVERSION   8   /* ABI version */
  43. #define EI_PAD      9   /* Start of padding bytes */
  44. #define EI_NIDENT   16  /* Size of e_ident[] */
  45.  
  46. /* e_ident[EI_MAG0] to e_ident[EI_MAG3] */
  47. #define ELFMAG0     0x7f    /* e_ident[EI_MAG0] */
  48. #define ELFMAG1     'E' /* e_ident[EI_MAG1] */
  49. #define ELFMAG2     'L' /* e_ident[EI_MAG2] */
  50. #define ELFMAG3     'F' /* e_ident[EI_MAG3] */
  51.  
  52. /* e_ident[EI_CLASS] */
  53. #define ELFCLASSNONE    0   /* Invalid class */
  54. #define ELFCLASS32  1   /* 32-bit objects */
  55. #define ELFCLASS64  2   /* 64-bit objects */
  56.  
  57. /* e_ident[EI_DATA] */
  58. #define ELFDATANONE 0   /* Invalid data encoding */
  59. #define ELFDATA2LSB 1   /* little endian */
  60. #define ELFDATA2MSB 2   /* big endian */
  61.  
  62. /* e_ident[EI_VERSION] */
  63. #define EV_NONE     0   /* Invalid version */
  64. #define EV_CURRENT  1   /* Current version */
  65.  
  66. /* e_type */
  67. #define ET_NONE     0   /* No file type */
  68. #define ET_REL      1   /* Relocatable file */
  69. #define ET_EXEC     2   /* Executable file */
  70. #define ET_DYN      3   /* Shared object file */
  71. #define ET_CORE     4   /* Core file */
  72.  
  73. /* e_machine */
  74. #define EM_PPC      20  /* PowerPC 32-bit */
  75. #define EM_PPC64    21  /* PowerPC 64-bit */
  76.  
  77. typedef struct {
  78.     unsigned char   e_ident[EI_NIDENT];
  79.     Elf32_Half  e_type;
  80.     Elf32_Half  e_machine;
  81.     Elf32_Word  e_version;
  82.     Elf32_Addr  e_entry;
  83.     Elf32_Off   e_phoff;
  84.     Elf32_Off   e_shoff;
  85.     Elf32_Word  e_flags;
  86.     Elf32_Half  e_ehsize;
  87.     Elf32_Half  e_phentsize;
  88.     Elf32_Half  e_phnum;
  89.     Elf32_Half  e_shentsize;
  90.     Elf32_Half  e_shnum;
  91.     Elf32_Half  e_shstrndx;
  92. } Elf32_Ehdr;
  93.  
  94. typedef struct {
  95.     unsigned char   e_ident[EI_NIDENT];
  96.     Elf64_Half  e_type;
  97.     Elf64_Half  e_machine;
  98.     Elf64_Word  e_version;
  99.     Elf64_Addr  e_entry;
  100.     Elf64_Off   e_phoff;
  101.     Elf64_Off   e_shoff;
  102.     Elf64_Word  e_flags;
  103.     Elf64_Half  e_ehsize;
  104.     Elf64_Half  e_phentsize;
  105.     Elf64_Half  e_phnum;
  106.     Elf64_Half  e_shentsize;
  107.     Elf64_Half  e_shnum;
  108.     Elf64_Half  e_shstrndx;
  109. } Elf64_Ehdr;
  110.  
  111. /*
  112. * Program Header
  113. */
  114.  
  115. /* Segment Types, p_type */
  116. #define PT_NULL     0
  117. #define PT_LOAD     1
  118. #define PT_DYNAMIC  2
  119. #define PT_INTERP   3
  120. #define PT_NOTE     4
  121. #define PT_SHLIB    5
  122. #define PT_PHDR     6
  123. #define PT_LOOS     0x60000000
  124. #define PT_HIOS     0x6fffffff
  125. #define PT_LOPROC   0x70000000
  126. #define PT_HIPROC   0x7fffffff
  127.  
  128. typedef struct {
  129.     Elf32_Word  p_type;
  130.     Elf32_Off   p_offset;
  131.     Elf32_Addr  p_vaddr;
  132.     Elf32_Addr  p_paddr;
  133.     Elf32_Word  p_filesz;
  134.     Elf32_Word  p_memsz;
  135.     Elf32_Word  p_flags;
  136.     Elf32_Word  p_align;
  137. } Elf32_Phdr;
  138.  
  139. typedef struct {
  140.     Elf64_Word  p_type;
  141.     Elf64_Word  p_flags;
  142.     Elf64_Off   p_offset;
  143.     Elf64_Addr  p_vaddr;
  144.     Elf64_Addr  p_paddr;
  145.     Elf64_Xword p_filesz;
  146.     Elf64_Xword p_memsz;
  147.     Elf64_Xword p_align;
  148. } Elf64_Phdr;
  149.  
  150. /*
  151. * Section Header
  152. */
  153.  
  154. /* sh_type */
  155. #define SHT_NULL    0   /* Section header table entry unused */
  156. #define SHT_PROGBITS    1   /* Program data */
  157. #define SHT_SYMTAB  2   /* Symbol table */
  158. #define SHT_STRTAB  3   /* String table */
  159. #define SHT_RELA    4   /* Relocation entries with addends */
  160. #define SHT_HASH    5   /* Symbol hash table */
  161. #define SHT_DYNAMIC 6   /* Dynamic linking information */
  162. #define SHT_NOTE    7   /* Notes */
  163. #define SHT_NOBITS  8   /* Program space with no data (bss) */
  164. #define SHT_REL     9   /* Relocation entries, no addends */
  165. #define SHT_SHLIB   10  /* Reserved */
  166. #define SHT_DYNSYM  11  /* Dynamic linker symbol table */
  167.  
  168. #define SHF_WRITE        (1 << 0)   /* Writable */
  169. #define SHF_ALLOC        (1 << 1)   /* Occupies memory during execution */
  170. #define SHF_EXECINSTR        (1 << 2)   /* Executable */
  171. #define SHF_MERGE        (1 << 4)   /* Might be merged */
  172. #define SHF_STRINGS      (1 << 5)   /* Contains nul-terminated strings */
  173. #define SHF_INFO_LINK        (1 << 6)   /* `sh_info' contains SHT index */
  174. #define SHF_LINK_ORDER       (1 << 7)   /* Preserve order after combining */
  175. #define SHF_OS_NONCONFORMING (1 << 8)   /* Non-standard OS specific handling
  176. required */
  177. #define SHF_MASKOS       0x0ff00000 /* OS-specific.  */
  178. #define SHF_MASKPROC         0xf0000000 /* Processor-specific */
  179.  
  180.  
  181. typedef struct {
  182.     Elf32_Word  sh_name;
  183.     Elf32_Word  sh_type;
  184.     Elf32_Word  sh_flags;
  185.     Elf32_Addr  sh_addr;
  186.     Elf32_Off   sh_offset;
  187.     Elf32_Word  sh_size;
  188.     Elf32_Word  sh_link;
  189.     Elf32_Word  sh_info;
  190.     Elf32_Word  sh_addralign;
  191.     Elf32_Word  sh_entsize;
  192. } Elf32_Shdr;
  193.  
  194. typedef struct {
  195.     Elf64_Word      sh_name;
  196.     Elf64_Word      sh_type;
  197.     Elf64_Xword     sh_flags;
  198.     Elf64_Addr      sh_addr;
  199.     Elf64_Off       sh_offset;
  200.     Elf64_Xword     sh_size;
  201.     Elf64_Word      sh_link;
  202.     Elf64_Word      sh_info;
  203.     Elf64_Xword     sh_addralign;
  204.     Elf64_Xword     sh_entsize;
  205. } Elf64_Shdr;
  206.  
  207. /* Special section indices.  */
  208.  
  209. #define SHN_UNDEF   0       /* Undefined section */
  210. #define SHN_LORESERVE   0xff00      /* Start of reserved indices */
  211. #define SHN_LOPROC  0xff00      /* Start of processor-specific */
  212. #define SHN_HIPROC  0xff1f      /* End of processor-specific */
  213. #define SHN_LOOS    0xff20      /* Start of OS-specific */
  214. #define SHN_HIOS    0xff3f      /* End of OS-specific */
  215. #define SHN_ABS     0xfff1      /* Associated symbol is absolute */
  216. #define SHN_COMMON  0xfff2      /* Associated symbol is common */
  217. #define SHN_XINDEX  0xffff      /* Index is in extra table.  */
  218. #define SHN_HIRESERVE   0xffff      /* End of reserved indices */
  219.  
  220. /*
  221. * Symbol Header
  222. */
  223.  
  224. typedef struct {
  225.     Elf32_Word  st_name;
  226.     Elf32_Word  st_value;
  227.     Elf32_Word  st_size;
  228.     unsigned char   st_info;
  229.     unsigned char   st_other;
  230.     Elf32_Half  st_shndx;
  231. } Elf32_Sym;
  232.  
  233.  
  234. /* Relocation table entry without addend (in section of type SHT_REL).  */
  235.  
  236. typedef struct
  237. {
  238.     Elf32_Addr  r_offset;       /* Address */
  239.     Elf32_Word  r_info;         /* Relocation type and symbol index */
  240. } Elf32_Rel;
  241.  
  242. /* I have seen two different definitions of the Elf64_Rel and
  243. Elf64_Rela structures, so we'll leave them out until Novell (or
  244. whoever) gets their act together.  */
  245. /* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */
  246.  
  247. typedef struct
  248. {
  249.     Elf64_Addr  r_offset;       /* Address */
  250.     Elf64_Xword r_info;         /* Relocation type and symbol index */
  251. } Elf64_Rel;
  252.  
  253. /* Relocation table entry with addend (in section of type SHT_RELA).  */
  254.  
  255. typedef struct
  256. {
  257.     Elf32_Addr  r_offset;       /* Address */
  258.     Elf32_Word  r_info;         /* Relocation type and symbol index */
  259.     Elf32_Sword r_addend;       /* Addend */
  260. } Elf32_Rela;
  261.  
  262. typedef struct
  263. {
  264.     Elf64_Addr  r_offset;       /* Address */
  265.     Elf64_Xword r_info;         /* Relocation type and symbol index */
  266.     Elf64_Sxword    r_addend;       /* Addend */
  267. } Elf64_Rela;
  268.  
  269. /* How to extract and insert information held in the r_info field.  */
  270.  
  271. #define ELF32_R_SYM(val)        ((val) >> 8)
  272. #define ELF32_R_TYPE(val)       ((val) & 0xff)
  273. #define ELF32_R_INFO(sym, type)     (((sym) << 8) + ((type) & 0xff))
  274.  
  275. #define ELF64_R_SYM(i)          ((i) >> 32)
  276. #define ELF64_R_TYPE(i)         ((i) & 0xffffffff)
  277. #define ELF64_R_INFO(sym,type)      ((((Elf64_Xword) (sym)) << 32) + (type))
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284. typedef struct _ELF_section_t
  285. {
  286.     Elf32_Shdr header;
  287.     const char* name;
  288.     char* data;
  289. } ELF_section_t;
  290.  
  291. typedef struct _ELF_segment_t
  292. {
  293.     Elf32_Phdr header;
  294.     unsigned char* pointer;
  295.     unsigned char* data;
  296. } ELF_segment_t;
  297.  
  298. typedef struct
  299. {
  300.     const char* name;
  301.     unsigned int vma;
  302.     unsigned int size;
  303.     int section;
  304.     unsigned char resolved;
  305.     unsigned char foreign;
  306. } ELF_symbol_t;
  307.  
  308. typedef struct _ELF_t
  309. {
  310.     unsigned int endian;
  311.     unsigned int relocatable;
  312.     unsigned int sectionCount;
  313.     unsigned int segmentCount;
  314.     unsigned int symbolCount;
  315.     unsigned int entrypoint;
  316.     ELF_section_t* sections;
  317.     ELF_segment_t* segments;
  318.     ELF_symbol_t* symbols;
  319.     unsigned int symbolsSection;
  320.     unsigned int symbolNamesSection;
  321.     unsigned int paramSection;  // cg parameters are now a proper elf section
  322. } ELF_t;
  323.  
  324. typedef struct
  325. {
  326.     unsigned int relative;
  327.     unsigned int shift;
  328.     unsigned int size;
  329.     unsigned int position;
  330.     unsigned int mask;
  331. } ELF_rel_type_t;
  332.  
  333. ELF_t* readElfFromFile(const char* filename);
  334. ELF_t* readElfFromMemory(const char* memory, unsigned int size);
  335. ELF_section_t* findSection(const ELF_t* elf, const char* name);
  336. int lookupSymbol(const ELF_t* elf, const char* name);
  337. int lookupResolvedSymbol(const ELF_t* elf, const char* name);
  338. const Elf32_Sym* getSymbolByIndex(const ELF_t* elf, int idx);
  339. int resolveElf(ELF_t* main_elf, ELF_t* elf);
  340. int relocateSymbols(ELF_t* elf, unsigned int origin);
  341. int loadSectionsToMemory(ELF_t* elf, char* memory, int memorySize, unsigned int origin);
  342. void doRelocations(ELF_t* elf, char* memory, int memorySize, int origin, const ELF_rel_type_t* rel_types, unsigned int rel_types_count);
  343. int loadElfToMemory(unsigned char* memory, unsigned int size, unsigned int load_address, ELF_t* elf);
  344. void freeElf(ELF_t* elf);
  345.  
  346. //in place API
  347. const char *findSectionInPlace(const char* memory, unsigned int size, const char *name, size_t *sectionSize);
  348. const char *findSymbolSectionInPlace(const char *memory, unsigned int size, size_t *symbolSize, size_t *symbolCount, const char **symbolstrtab);
  349. int lookupSymbolValueInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, const char *name);
  350. const char *getSymbolByIndexInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, int index);
  351.  
  352. void spuDoRelocations(ELF_t* elf, char* memory, int memorySize, int origin);
  353.  
  354. Elf32_Half endian_half(int endian, Elf32_Half v);
  355. Elf32_Word endian_word(int endian, Elf32_Word v);
  356. #define endian_addr(e, v)   endian_word(e, v)
  357. #define endian_off(e, v)    endian_word(e, v)
  358. #define endian_size(e, v)   endian_half(e, v)
  359.  
  360.  
  361.  
  362.  
  363. #define IS_LITLLE_ENDIAN 0
  364.  
  365. #if IS_LITLLE_ENDIAN
  366. # define IS_OPPOSITE_ELF_ENDIAN(s)  ((s) == ELFDATA2LSB)
  367. #else
  368. # define IS_OPPOSITE_ELF_ENDIAN(s)  ((s) == ELFDATA2MSB)
  369. #endif
  370.  
  371. Elf32_Half endian_half(int endian, Elf32_Half v)
  372. {
  373.     if (IS_OPPOSITE_ELF_ENDIAN(endian)) {
  374.         v = (v >> 8 & 0x00ff) | (v << 8 & 0xff00);
  375.     }
  376.     return v;
  377. }
  378.  
  379. Elf32_Word endian_word(int endian, Elf32_Word v)
  380. {
  381.     if (IS_OPPOSITE_ELF_ENDIAN(endian)) {
  382.         v = (v >> 16 & 0x0000ffffUL) | (v << 16);
  383.         v = (v >> 8 & 0x00ff00ffUL) | (v << 8 & 0xff00ff00UL);
  384.     }
  385.     return v;
  386. }
  387.  
  388. Elf32_Sword endian_sword(int endian, Elf32_Sword v)
  389. {
  390.     return (Elf32_Sword)endian_word(endian, (Elf32_Word)v);
  391. }
  392.  
  393. inline void endianSwapEhdr(int endian, Elf32_Ehdr *ehdr)
  394. {
  395.     ehdr->e_type = endian_half(endian, ehdr->e_type);
  396.     ehdr->e_machine = endian_half(endian, ehdr->e_machine);
  397.     ehdr->e_version = endian_word(endian, ehdr->e_version);
  398.     ehdr->e_entry = endian_addr(endian, ehdr->e_entry);
  399.     ehdr->e_phoff = endian_off(endian, ehdr->e_phoff);
  400.     ehdr->e_shoff = endian_off(endian, ehdr->e_shoff);
  401.     ehdr->e_flags = endian_word(endian, ehdr->e_flags);
  402.     ehdr->e_ehsize = endian_half(endian, ehdr->e_ehsize);
  403.     ehdr->e_phentsize = endian_half(endian, ehdr->e_phentsize);
  404.     ehdr->e_phnum = endian_half(endian, ehdr->e_phnum);
  405.     ehdr->e_shentsize = endian_half(endian, ehdr->e_shentsize);
  406.     ehdr->e_shnum = endian_half(endian, ehdr->e_shnum);
  407.     ehdr->e_shstrndx = endian_half(endian, ehdr->e_shstrndx);
  408. }
  409.  
  410. inline void endianSwapShdr(int endian, Elf32_Shdr *shdr)
  411. {
  412.     shdr->sh_name = endian_word(endian, shdr->sh_name);
  413.     shdr->sh_type = endian_word(endian, shdr->sh_type);
  414.     shdr->sh_flags = endian_word(endian, shdr->sh_flags);
  415.     shdr->sh_addr = endian_addr(endian, shdr->sh_addr);
  416.     shdr->sh_offset = endian_off(endian, shdr->sh_offset);
  417.     shdr->sh_size = endian_word(endian, shdr->sh_size);
  418.     shdr->sh_link = endian_word(endian, shdr->sh_link);
  419.     shdr->sh_info = endian_word(endian, shdr->sh_info);
  420.     shdr->sh_addralign = endian_word(endian, shdr->sh_addralign);
  421.     shdr->sh_entsize = endian_word(endian, shdr->sh_entsize);
  422. }
  423.  
  424. inline void endianSwapPhdr(int endian, Elf32_Phdr *phdr)
  425. {
  426.     phdr->p_type = endian_word(endian, phdr->p_type);
  427.     phdr->p_offset = endian_off(endian, phdr->p_offset);
  428.     phdr->p_vaddr = endian_addr(endian, phdr->p_vaddr);
  429.     phdr->p_paddr = endian_addr(endian, phdr->p_paddr);
  430.     phdr->p_filesz = endian_word(endian, phdr->p_filesz);
  431.     phdr->p_memsz = endian_word(endian, phdr->p_memsz);
  432.     phdr->p_flags = endian_word(endian, phdr->p_flags);
  433.     phdr->p_align = endian_word(endian, phdr->p_align);
  434. }
  435.  
  436. inline void endianSwapSym(int endian, Elf32_Sym *sym)
  437. {
  438.     sym->st_name = endian_word(endian, sym->st_name);
  439.     sym->st_value = endian_word(endian, sym->st_value);
  440.     sym->st_size = endian_word(endian, sym->st_size);
  441.     sym->st_shndx = endian_half(endian, sym->st_shndx);
  442. }
  443.  
  444. inline void endianSwapRel(int endian, Elf32_Rel *rel)
  445. {
  446.     rel->r_offset = endian_addr(endian, rel->r_offset);
  447.     rel->r_info = endian_word(endian, rel->r_info);
  448. }
  449.  
  450. inline void endianSwapRela(int endian, Elf32_Rela *rel)
  451. {
  452.     endianSwapRel(endian, (Elf32_Rel *)rel);
  453.     rel->r_addend = endian_sword(endian, rel->r_addend);
  454. }
  455.  
  456. struct _Streamer_t;
  457.  
  458. typedef int(*readFunction)(void* buffer, int count, struct _Streamer_t* streamer);
  459. typedef int(*seekFunction)(int count, struct _Streamer_t* streamer);
  460.  
  461. typedef struct _Streamer_t
  462. {
  463.     readFunction fread;
  464.     seekFunction fseek;
  465.     const void *handle;
  466.     unsigned int pointer;
  467.     unsigned int size;
  468. } Streamer_t;
  469.  
  470.  
  471.  
  472. int file_fread(void *buffer, int count, Streamer_t *streamer)
  473. {
  474.     FILE *fp = (FILE *)streamer->handle;
  475.     return fread(buffer, count, 1, fp);
  476. }
  477.  
  478. int file_fseek(int count, Streamer_t *streamer)
  479. {
  480.     FILE *fp = (FILE *)streamer->handle;
  481.     return fseek(fp, count, SEEK_SET);
  482. }
  483.  
  484. int memory_fread(void *buffer, int count, Streamer_t *streamer)
  485. {
  486.     const char *memory = (const char *)streamer->handle;
  487.     // temporarily using 0 as a value to handle elfs transparently.  to be removed after sdk 0.8.5
  488.     if (streamer->pointer + count>streamer->size && streamer->size != 0) return 0;
  489.     if (streamer->pointer<0) return 0;
  490.     memcpy(buffer, memory + streamer->pointer, count);
  491.     streamer->pointer += count;
  492.     return 1;
  493. }
  494.  
  495. int memory_fseek(int count, Streamer_t *streamer)
  496. {
  497.     // temporarily using 0 as a value to handle elfs transparently.  to be removed after sdk 0.8.5
  498.     if (count>(int)streamer->size && streamer->size != 0) count = streamer->size;
  499.     if (count<0) count = 0;
  500.     streamer->pointer = count;
  501.     return 0;
  502. }
  503.  
  504. int readSection(ELF_t *elf, Elf32_Off secoff, unsigned int sectionIdx, Streamer_t *streamer)
  505. {
  506.     // given a section header index, read in the section header and
  507.     // the data, setting section->data with a pointer to the allocated memory
  508.  
  509.     // TODO: *** make sure loading a section respects the alignment specified
  510.     // TODO: *** in "sh_addralign", which is currently ignored
  511.  
  512.     unsigned int endian = elf->endian;
  513.  
  514.     // if we're requesting an out-of-bounds section header, give up.
  515.     if (sectionIdx >= elf->sectionCount)
  516.     {
  517.         return -1;
  518.     }
  519.  
  520.     // get a pointer to the section header (this assumes the section storage has been allocated)
  521.     ELF_section_t *section = elf->sections + sectionIdx;
  522.  
  523.     // attempt to read the section header from the section header table
  524.     // first checking that the section header is empty (no shdr loaded)
  525.  
  526.     // TODO: *** assumes uninitialised data is zero filled and that a section of
  527.     // TODO: *** type SHT_NULL will never occur or has no use in a valid file
  528.  
  529.     if (section->header.sh_type == SHT_NULL)
  530.     {
  531.         // first, attempt to seek the location of the section header in the file
  532.         if (streamer->fseek(secoff + sectionIdx * sizeof(Elf32_Shdr), streamer) < 0)
  533.         {
  534.             // seek failed, return failure
  535.             return -1;
  536.         }
  537.  
  538.         // if the seek worked, read an Elf32_Shdr structure form the file
  539.         if (streamer->fread(&section->header, sizeof(Elf32_Shdr), streamer) < 1)
  540.         {
  541.             // read failed, return failure
  542.             return -1;
  543.         }
  544.  
  545.         // make sure the structure just read is endian-swapped for this platform.
  546.         endianSwapShdr(endian, &section->header);
  547.     }
  548.  
  549.     // find out the size of the section
  550.     unsigned int size = section->header.sh_size;
  551.     if (size <= 0 || section->data != 0)
  552.     {
  553.         // no data to read or data already read, return success.
  554.         return 0;
  555.     }
  556.  
  557.     // now we have the header, allocate storage for the section data
  558.     section->data = (char *)malloc(size);
  559.     if (!section->data)
  560.     {
  561.         // memory allocation problem, return failure.
  562.         return -1;
  563.     }
  564.  
  565.     // attempt to seek the location of the section data in the ELF file.
  566.     if (streamer->fseek(section->header.sh_offset, streamer) < 0)
  567.     {
  568.         // seek failed, release memory and return failure
  569.         free(section->data);
  570.         section->data = NULL;
  571.         return -1;
  572.     }
  573.  
  574.     // if the seek succeeded, read the data block into memory
  575.     if (streamer->fread(section->data, size, streamer) < 1)
  576.     {
  577.         // read failed, release memory and return failure
  578.         free(section->data);
  579.         section->data = NULL;
  580.         return -1;
  581.     }
  582.  
  583.     // return success
  584.     return 0;
  585. }
  586.  
  587. int readSymbolSection(ELF_t* elf, Elf32_Off shoff, int sectionIdx, Streamer_t* streamer)
  588. {
  589.     // first, read the section header
  590.     if (readSection(elf, shoff, sectionIdx, streamer)<0)
  591.     {
  592.         return -1;
  593.     }
  594.  
  595.     // get a direct pointer to the section record
  596.     ELF_section_t* section = elf->sections + sectionIdx;
  597.  
  598.     // if the section contains data that has been loaded...
  599.     if (section->data)
  600.     {
  601.         // get the size of a single entry in the section (never assume about padding)
  602.         int esize = section->header.sh_entsize;
  603.  
  604.         // calculate the number of elements in this data block
  605.         elf->symbolCount = section->header.sh_size / esize;
  606.  
  607.         // if there are any symbols in this data block, expand the symbols into the elf record
  608.         if (elf->symbolCount > 0)
  609.         {
  610.             // allocate memory for all the the symbol records as a block
  611.             elf->symbols = (ELF_symbol_t*)malloc(elf->symbolCount * sizeof(ELF_symbol_t));
  612.             if (!elf->symbols)
  613.             {
  614.                 // allocation for symbol records failed
  615.                 return -1;
  616.             }
  617.  
  618.             // walk through the symbols expanding the symtab entry into a symbol record
  619.             ELF_symbol_t* symbol = elf->symbols;
  620.             char* data = section->data;
  621.             for (unsigned int i = 0; i<elf->symbolCount; ++i)
  622.             {
  623.                 // get a pointer to the symbol
  624.                 Elf32_Sym* elf_sym = (Elf32_Sym*)data;
  625.  
  626.                 // swap the data to match the endinness of this machine
  627.                 endianSwapSym(elf->endian, elf_sym);
  628.  
  629.                 // expand the information into a symbol record
  630.                 // NOTE: the address of the string table (strtab) is not necessarily known yet
  631.  
  632.                 // offset of symbol name in the strtab
  633.                 symbol->name = (char*)(0) + elf_sym->st_name;
  634.  
  635.                 // is this the definition of a symbol relative to a section?
  636.                 symbol->resolved = (elf_sym->st_shndx != SHN_UNDEF);
  637.  
  638.                 // size of the symbol (non-zero if the symbol is a function)
  639.                 symbol->size = elf_sym->st_size;
  640.  
  641.                 // address within the section where the symbol is defined
  642.                 // TODO: *** this seems to assume the symbol is always an STT_OBJECT
  643.                 symbol->vma = elf_sym->st_value;
  644.  
  645.                 // note the section where the symbol is defined, if known
  646.                 symbol->section = symbol->resolved ? elf_sym->st_shndx : 0;
  647.  
  648.                 // is the symbol defined in the current elf or defined externally?
  649.                 // TODO: this assumes only two contexts for a symbol to be defined from.
  650.                 symbol->foreign = 0;
  651.  
  652.                 // TODO: *** the symbol record makes no note of the type or binding of the symbol
  653.  
  654.                 // advance the pointers for the next iteration
  655.                 data += esize;
  656.                 ++symbol;
  657.             }
  658.         }
  659.     }
  660.  
  661.     // return success
  662.     return 0;
  663. }
  664.  
  665. void retrieveSymbolNames(ELF_t* elf)
  666. {
  667.     // by now we have loaded the symtab and it's associated strtab
  668.     // run through each symbol and patch up the name pointer to the strtab
  669.  
  670.     // convert the address of the strtab into an integer offset from zero
  671.     unsigned int offset = elf->sections[elf->symbolNamesSection].data - (char *)NULL;
  672.  
  673.     // add that offset to the strtab offset already in each symbol record.
  674.     ELF_symbol_t* symbol = elf->symbols;
  675.     for (unsigned int i = 0; i<elf->symbolCount; ++i)
  676.     {
  677.         symbol->name += offset;
  678.         ++symbol;
  679.     }
  680. }
  681.  
  682. int readRelSection(ELF_t* elf, Elf32_Off secoff, int sectionIdx, Streamer_t* streamer)
  683. {
  684.     // read and record the relocation records associated with a section
  685.  
  686.     // first, read in the data into the section record
  687.     if (readSection(elf, secoff, sectionIdx, streamer) < 0)
  688.     {
  689.         // read failed, return failure
  690.         return -1;
  691.     }
  692.  
  693.     // get a direct pointer to the section record
  694.     ELF_section_t* section = elf->sections + sectionIdx;
  695.  
  696.     // is the section a REL+ADDEND or REL type?
  697.     int rela = (section->header.sh_type == SHT_RELA) ? 1 : 0;
  698.  
  699.     // if the section record has data...
  700.     if (section->data)
  701.     {
  702.         char* data = section->data;
  703.  
  704.         // find out how many relocation records there are in this data section
  705.         int esize = section->header.sh_entsize;
  706.         int num = section->header.sh_size / esize;
  707.  
  708.         // loop over all relocation records
  709.         for (int i = 0; i<num; ++i)
  710.         {
  711.             // swap the endianness of the data to match this machine
  712.             if (rela)
  713.             {
  714.                 endianSwapRela(elf->endian, (Elf32_Rela*)data);
  715.             }
  716.             else
  717.             {
  718.                 endianSwapRel(elf->endian, (Elf32_Rel*)data);
  719.             }
  720.  
  721.             // update the pointer to the next relocation record
  722.             data += esize;
  723.         }
  724.     }
  725.  
  726.     // return success
  727.     return 0;
  728. }
  729.  
  730. ELF_t *readElf(Streamer_t *streamer)
  731. {
  732.     ELF_t *elf;
  733.     Elf32_Ehdr ehdr;
  734.  
  735.     // read just the ELF header
  736.     if (streamer->fread(&ehdr, sizeof(Elf32_Ehdr), streamer) < 1)
  737.     {
  738.         // read failed.
  739.         return NULL;
  740.     }
  741.     if (!(ehdr.e_ident[EI_MAG0] == ELFMAG0 &&
  742.         ehdr.e_ident[EI_MAG1] == ELFMAG1 &&
  743.         ehdr.e_ident[EI_MAG2] == ELFMAG2 &&
  744.         ehdr.e_ident[EI_MAG3] == ELFMAG3))
  745.     {
  746.         // file is not an ELF file, header does not match the magic token "\0x7fELF"
  747.         return NULL;
  748.     }
  749.  
  750.     // allocate memory and zero it
  751.     elf = (ELF_t *)malloc(sizeof(ELF_t));
  752.     if (!elf)
  753.     {
  754.         // memory allocation failed.
  755.         return NULL;
  756.     }
  757.  
  758.     elf->paramSection = 0;
  759.     // get the endian flag
  760.     elf->endian = ehdr.e_ident[EI_DATA];
  761.  
  762.     // shuffle the Ehdr structure to match the machine endianness
  763.     endianSwapEhdr(elf->endian, &ehdr);
  764.  
  765.     // check to see if the file type is a relocatable file (object file).
  766.     // *** NOTE: unclear, we could equally call it a shared object or a dynamic library.
  767.     elf->relocatable = (ehdr.e_type == ET_REL);
  768.  
  769.     // record the file offset of the section header table
  770.     Elf32_Off shoff = ehdr.e_shoff;
  771.  
  772.     // record the number of sections in the section header table.
  773.     elf->sectionCount = ehdr.e_shnum;
  774.  
  775.     // allocate memory for the section header table
  776.     // TODO: *** ELF_section_t should be using e_shentsize instead of sizeof()
  777.     elf->sections = (ELF_section_t*)malloc(elf->sectionCount * sizeof(ELF_section_t));
  778.     if (!elf->sections)
  779.     {
  780.         // section header memory allocation failed, clean up and exit.
  781.         freeElf(elf);
  782.         return NULL;
  783.     }
  784.  
  785.     // clear the section header table (readSection requires this)
  786.     memset(elf->sections, 0, elf->sectionCount * sizeof(ELF_section_t));
  787.  
  788.     // record the number of segments in this file (and there should be none for a shader)
  789.     elf->segmentCount = ehdr.e_phnum;
  790.  
  791.     if (elf->segmentCount)
  792.     {
  793.         // allocate space for the segment header table
  794.         elf->segments = (ELF_segment_t *)malloc(elf->segmentCount * sizeof(ELF_segment_t));
  795.         if (!elf->segments)
  796.         {
  797.             // segment header memory allocation failed, clean up and exit.
  798.             freeElf(elf);
  799.             return NULL;
  800.         }
  801.     }
  802.     else
  803.         elf->segments = NULL;
  804.  
  805.     // initialise the symbol table as empty
  806.     elf->symbols = NULL;
  807.     elf->symbolCount = 0;
  808.  
  809.     // record which section header points to the section header string table (.shstrtab)
  810.     int stringSectionIndex = ehdr.e_shstrndx;
  811.  
  812.     // read in the section header string table from the section header table
  813.     if (readSection(elf, shoff, stringSectionIndex, streamer)<0)
  814.     {
  815.         // if reading the section header string table fails, give up.
  816.         freeElf(elf);
  817.         return NULL;
  818.     }
  819.  
  820.     // get a pointer to the section header string table
  821.     char* shstrtab = elf->sections[stringSectionIndex].data;
  822.  
  823.     // seek the beginning of the section header table
  824.     // TODO *** which we already did while loading the section header string table
  825.     if (streamer->fseek(shoff, streamer) < 0)
  826.     {
  827.         freeElf(elf);
  828.         return NULL;
  829.     }
  830.  
  831.     // read the section header table entries one by one
  832.     for (unsigned int i = 0; i<elf->sectionCount; ++i)
  833.     {
  834.         ELF_section_t* section = elf->sections + i;
  835.         if (streamer->fread(&section->header, sizeof(Elf32_Shdr), streamer) < 1)
  836.         {
  837.             freeElf(elf);
  838.             return NULL;
  839.         }
  840.  
  841.         // convert the structure read from the file to the endianness of this machine
  842.         endianSwapShdr(elf->endian, &section->header);
  843.  
  844.         // look up the section name in the shstrtab and record it as a char*
  845.         section->name = shstrtab + section->header.sh_name;
  846.     }
  847.  
  848.     // go through each section and load the associated data if there is any.
  849.     for (unsigned int i = 0; i<elf->sectionCount; i++)
  850.     {
  851.         ELF_section_t* section = elf->sections + i;
  852.  
  853.         // check the section type
  854.         switch (section->header.sh_type)
  855.         {
  856.         case SHT_SYMTAB:
  857.             // the section is a symbol table
  858.             if (readSymbolSection(elf, shoff, i, streamer)<0)
  859.             {
  860.                 // reading the symbol section failed, clean up and return failure
  861.                 freeElf(elf);
  862.                 return NULL;
  863.             }
  864.             // record which section contains the symbol table
  865.             // TODO: this assumes only one symbol table per elf (which is the ELF 1.1 standard)
  866.             elf->symbolsSection = i;
  867.             break;
  868.  
  869.         case SHT_REL:
  870.         case SHT_RELA:
  871.             // the section is a set of relocation records
  872.             if (readRelSection(elf, shoff, i, streamer)<0)
  873.             {
  874.                 // reading the relocation records failed, clean up and return failure
  875.                 freeElf(elf);
  876.                 return NULL;
  877.             }
  878.             break;
  879.  
  880.         default:
  881.             // check to see whether the section allocates space in an executable
  882.             // TODO: *** this covers not only SHT_PROGBITS and SHT_NOBITS sections
  883.             // TODO: *** but also SHT_STRTAB and SHT_HASH. Do we want this?
  884.             if ((elf->segmentCount == 0) && (section->header.sh_flags&SHF_ALLOC))
  885.             {
  886.                 // TODO: *** why must segmentCount be zero? So we have only one executable
  887.                 // TODO: *** section in the executable image?
  888.  
  889.                 // read in a block of executable instructions
  890.                 if (readSection(elf, shoff, i, streamer)<0)
  891.                 {
  892.                     // read failed, clean up and return failure.
  893.                     freeElf(elf);
  894.                     return NULL;
  895.                 }
  896.             }
  897.             break;
  898.  
  899.         }
  900.     }
  901.  
  902.     // if we have read in a symbol table and it contains symbols...
  903.     if ((elf->symbolsSection>0) && (elf->symbolCount>0))
  904.     {
  905.         // get a direct pointer to the symbol table record
  906.         ELF_section_t* section = elf->sections + elf->symbolsSection;
  907.  
  908.         // for a symbol table the sh_link field tells us which section the strtab is in
  909.         elf->symbolNamesSection = section->header.sh_link;
  910.  
  911.         // if there is no string table (strtab)...
  912.         if (elf->symbolNamesSection <= 0)
  913.         {
  914.             // clean up and return failure
  915.             freeElf(elf);
  916.             return NULL;
  917.         }
  918.  
  919.         // otherwise read in the strtab
  920.         if (readSection(elf, shoff, elf->symbolNamesSection, streamer)<0)
  921.         {
  922.             // read failed, clean up and return failure
  923.             freeElf(elf);
  924.             return NULL;
  925.         }
  926.  
  927.         // process the symbols to resolve pointers to their names
  928.         retrieveSymbolNames(elf);
  929.     }
  930.  
  931.     // next we turn our attention to program segments...
  932.  
  933.     // ----------------
  934.  
  935.     // get the size of a segment header record (program header)
  936.     Elf32_Half e_phentsize = ehdr.e_phentsize;
  937.  
  938.     // TODO: *** aren't we forgetting that segments and sections may well reference the same data?
  939.     for (unsigned int i = 0; i<elf->segmentCount; ++i)
  940.     {
  941.         // assuming that the ELF32_Phdr structure is embedded at the start of a
  942.         // e_phentsize block (the padding occurs after the structure), seek the
  943.         // beginning of the phdr record
  944.         if (streamer->fseek(ehdr.e_phoff + i * e_phentsize, streamer) < 0)
  945.         {
  946.             // seek failed, clean up and return failure
  947.             freeElf(elf);
  948.             return NULL;
  949.         }
  950.  
  951.         // read the segment header
  952.         if (streamer->fread(&elf->segments[i].header, sizeof(Elf32_Phdr), streamer) < 1)
  953.         {
  954.             // seek failed, clean up and return failure
  955.             freeElf(elf);
  956.             return NULL;
  957.         }
  958.  
  959.         // endian swap the phdr structure to match this machine
  960.         endianSwapPhdr(elf->endian, &elf->segments[i].header);
  961.  
  962.         // get the number of bytes of filespace this segment occupies
  963.         Elf32_Word p_filesz = elf->segments[i].header.p_filesz;
  964.  
  965.         // if the segment has no bytes, keep on looking for segments
  966.         if (p_filesz == 0) continue;
  967.  
  968.         // allocate space for the executable data plus extra padding for 128-byte alignment
  969.         elf->segments[i].pointer = (unsigned char *)malloc(p_filesz + 128);
  970.         if (!elf->segments[i].pointer)
  971.         {
  972.             // allocation failed, clean up and return failure
  973.             freeElf(elf);
  974.             return NULL;
  975.         }
  976.  
  977.         // make sure the data pointer is 128-byte aligned
  978.         elf->segments[i].data = (unsigned char *)(((long)(elf->segments[i].pointer + 127)) & ~127);
  979.  
  980.         // get the file offset of the executable data
  981.         Elf32_Off p_offset = elf->segments[i].header.p_offset;
  982.  
  983.         // attempt to seek the data
  984.         if (streamer->fseek(p_offset, streamer) < 0)
  985.         {
  986.             // seek failed, clean up and return failure
  987.             freeElf(elf);
  988.             return NULL;
  989.         }
  990.  
  991.         // if the seek succeeded, read the data into the aligned storage
  992.         if (streamer->fread(elf->segments[i].data, p_filesz, streamer) < 1)
  993.         {
  994.             // read failed, clean up and return failure
  995.             freeElf(elf);
  996.             return NULL;
  997.         }
  998.     }
  999.  
  1000.     // ----------------
  1001.  
  1002.     // finally record the entry point (which may be zero) in target memory space
  1003.     elf->entrypoint = ehdr.e_entry;
  1004.  
  1005.     // succeeded
  1006.     return elf;
  1007. }
  1008.  
  1009. ELF_t *readElfFromFile(const char *filename)
  1010. {
  1011.     FILE *fp;
  1012.     Streamer_t streamer;
  1013.  
  1014.     if ((fp = fopen(filename, "rb")) == NULL) return NULL;
  1015.  
  1016.     streamer.fread = file_fread;
  1017.     streamer.fseek = file_fseek;
  1018.     streamer.handle = fp;
  1019.     ELF_t *elf = readElf(&streamer);
  1020.  
  1021.     fclose(fp);
  1022.  
  1023.     return elf;
  1024. }
  1025.  
  1026. ELF_t *readElfFromMemory(const char *memory, unsigned int size)
  1027. {
  1028.     Streamer_t streamer;
  1029.  
  1030.     streamer.fread = memory_fread;
  1031.     streamer.fseek = memory_fseek;
  1032.     streamer.handle = memory;
  1033.     streamer.pointer = 0;
  1034.     streamer.size = size;
  1035.  
  1036.     ELF_t *elf = readElf(&streamer);
  1037.  
  1038.     return elf;
  1039. }
  1040.  
  1041. ELF_section_t *findSection(const ELF_t *elf, const char *name)
  1042. {
  1043.     unsigned int i;
  1044.     for (i = 0; i<elf->sectionCount; i++)
  1045.     {
  1046.         if (!strcmp(elf->sections[i].name, name)) return elf->sections + i;
  1047.     }
  1048.     return NULL;
  1049. }
  1050.  
  1051. const Elf32_Sym *getSymbolByIndex(const ELF_t *elf, int idx)
  1052. {
  1053.     if (!elf) return NULL;
  1054.     if (elf->symbolsSection <= 0) return NULL;
  1055.     ELF_section_t *section = elf->sections + elf->symbolsSection;
  1056.     if (!section->data) return NULL;
  1057.     if ((idx<0) || (idx >= (int)elf->symbolCount)) return NULL;
  1058.     return (Elf32_Sym *)(section->data + section->header.sh_entsize*idx);
  1059. }
  1060.  
  1061. int lookupSymbol(const ELF_t *elf, const char *name)
  1062. {
  1063.     unsigned int i;
  1064.     if (!elf || !name) return -1;
  1065.     ELF_symbol_t *symbol = elf->symbols;
  1066.     if (!symbol) return -1;
  1067.  
  1068.     for (i = 0; i<elf->symbolCount; ++i, ++symbol)
  1069.     {
  1070.         if (strcmp(name, symbol->name) == 0)
  1071.         {
  1072.             return i;
  1073.         }
  1074.     }
  1075.     return -1;
  1076. }
  1077.  
  1078. int lookupResolvedSymbol(const ELF_t *elf, const char *name)
  1079. {
  1080.     // given a symbol name, find out if it is defined (resolved) in
  1081.     // some section inside this ELF, and return it's index if it is found
  1082.     // or -1 if failed.
  1083.  
  1084.     if (NULL == elf || NULL == name)
  1085.     {
  1086.         // bad parameters, return failure
  1087.         return -1;
  1088.     }
  1089.  
  1090.     // if the elf has no symbols defined, return failure.
  1091.     ELF_symbol_t* symbol = elf->symbols;
  1092.     if (!symbol)
  1093.     {
  1094.         return -1;
  1095.     }
  1096.  
  1097.     // loop through each symbol looking for a resolved symbol with the correct name
  1098.     for (unsigned int i = 0; i<elf->symbolCount; ++i)
  1099.     {
  1100.         if (symbol->resolved)
  1101.         {
  1102.             if (strcmp(name, symbol->name) == 0)
  1103.             {
  1104.                 return i;
  1105.             }
  1106.         }
  1107.         ++symbol;
  1108.     }
  1109.     return -1;
  1110. }
  1111.  
  1112. int resolveElf(ELF_t *main_elf, ELF_t *elf)
  1113. {
  1114.     int unresolved = 0;
  1115.  
  1116.     // for each symbol in the secondary elf...
  1117.     for (unsigned int i = 0; i<elf->symbolCount; ++i)
  1118.     {
  1119.         ELF_symbol_t* symbol = elf->symbols + i;
  1120.  
  1121.         // if the symbol does not yet have a section it is defined in...
  1122.         if (!symbol->resolved)
  1123.         {
  1124.             // see if the unresolved symbol is defined by name in the main_elf first
  1125.             int symbolIndex = lookupResolvedSymbol(main_elf, symbol->name);
  1126.             if (symbolIndex >= 0)
  1127.             {
  1128.                 // symbol was found by name, patch the elf symbol table to point to
  1129.                 // to the found symbol (this does not create a memory leak, the symbol table
  1130.                 // is allcated as a whole).
  1131.                 *symbol = main_elf->symbols[symbolIndex]; // this symbol uses the main elf's name.
  1132.                 symbol->foreign = 1;
  1133.             }
  1134.             else
  1135.             {
  1136.                 symbolIndex = lookupResolvedSymbol(elf, symbol->name);
  1137.                 if (symbolIndex >= 0)
  1138.                 {
  1139.                     *symbol = elf->symbols[symbolIndex];
  1140.                 }
  1141.                 else
  1142.                 {
  1143.                     // unresolved symbol
  1144. #if REPORT_UNRESOLVED_SYMBOLS
  1145.                     printf("Unresolved : %s\n", symbol->name);
  1146. #endif
  1147.                     ++unresolved;
  1148.                     continue;
  1149.                 }
  1150.             }
  1151.         }
  1152.     }
  1153.     return unresolved;
  1154. }
  1155.  
  1156. int relocateSymbols(ELF_t *elf, unsigned int origin)
  1157. {
  1158.     // for each symbol in the relocation section, apply a base offset.
  1159.  
  1160.     // size is also used as the next free byte
  1161.     int size = 0;
  1162.  
  1163.     // for each section...
  1164.     for (unsigned int i = 0; i<elf->sectionCount; ++i)
  1165.     {
  1166.         ELF_section_t* section = elf->sections + i;
  1167.  
  1168.         // if the section is allocated in the executable image
  1169.         if (section->header.sh_flags & SHF_ALLOC)
  1170.         {
  1171.             // find out the byte alignment for this section
  1172.             unsigned int align = section->header.sh_addralign;
  1173.  
  1174.             // make sure the alignment is a power of two
  1175.             //assert((align&(align - 1)) == 0);
  1176.  
  1177.             // work out where, in the final image, the first byte of this section will reside
  1178.             unsigned int addr = (origin + size + align - 1) & ~(align - 1);
  1179.  
  1180.             // record this address in the ELF header
  1181.             section->header.sh_addr = addr;
  1182.  
  1183.             // update the size of the section (works for SHT_NOBITS sections too)
  1184.             size = addr - origin + section->header.sh_size;
  1185.         }
  1186.     }
  1187.  
  1188.     // for each symbol...
  1189.     for (unsigned int i = 0; i<elf->symbolCount; ++i)
  1190.     {
  1191.         ELF_symbol_t* symbol = elf->symbols + i;
  1192.  
  1193.         // if the symbol is resolved (has a section) and is not foreign (?)
  1194.         if (symbol->resolved && !symbol->foreign)
  1195.         {
  1196.             // find out which section the symbol is defined in
  1197.             int idx = symbol->section;
  1198.  
  1199.             // check that this is a valid section (section 0 is always null)
  1200.             //assert(idx >= 0);
  1201.  
  1202.             if (idx < (int)elf->sectionCount)
  1203.             {
  1204.                 // add the section base address to the symbol offset
  1205.                 symbol->vma += elf->sections[idx].header.sh_addr;
  1206.             }
  1207.             else if (idx == SHN_COMMON)
  1208.             {
  1209.                 // if the symbol lives in a common block
  1210.                 // TODO: *** this should never happen.
  1211.                 //JS_assert(0);
  1212.  
  1213.                 // align size+origin on symbol->vma which is the alignment requirement
  1214.                 unsigned int align = symbol->vma;
  1215.                 //assert((align&(align - 1)) == 0);
  1216.                 unsigned int addr = (size + origin + align - 1) &~(align - 1);
  1217.                 symbol->vma = addr;
  1218.                 size = addr - origin + symbol->size;
  1219.             }
  1220.             else
  1221.             {
  1222.                 // section has an absolute address that cannot be changed.
  1223.                 // TODO: *** this should never happen.
  1224.                 //assert(idx == SHN_ABS);
  1225.             }
  1226.         }
  1227.     }
  1228.     return size;
  1229. }
  1230.  
  1231. int loadSectionsToMemory(ELF_t* elf, char* memory, int memorySize, unsigned int origin)
  1232. {
  1233.     // copy out each section from the elf, in order, into the buffer at "memory"
  1234.     // not exceeding the memorySize.
  1235.  
  1236.     int offset = 0;
  1237.     for (unsigned int i = 0; i<elf->sectionCount; ++i)
  1238.     {
  1239.         // get a pointer to the section
  1240.         ELF_section_t* section = elf->sections + i;
  1241.         // if the section should be allocated in the executable image...
  1242.         if (section->header.sh_flags & SHF_ALLOC)
  1243.         {
  1244.             // get it's size
  1245.             int size = section->header.sh_size;
  1246.  
  1247.             // work out where the section is to be put
  1248.             // NOTE: *** this resets the offset to the precalculated address for the section
  1249.             // NOTE: *** this also respects the alignment calculated earlier.
  1250.             offset = section->header.sh_addr - origin;
  1251.  
  1252.             // do not overflow the memory size
  1253.             if (offset + size > memorySize)
  1254.             {
  1255.                 // memory overflowed, return failure
  1256.                 return -1;
  1257.             }
  1258.  
  1259.             // copy the section data into the executable image at the location
  1260.             memcpy(memory + offset, section->data, size);
  1261.  
  1262.             // update the offset.
  1263.             offset += size;
  1264.         }
  1265.     }
  1266.  
  1267.     // initialize the bss by zeroing out all the remaining space
  1268.     // NOTE: *** this only works if the final section allocated is the last one
  1269.     // NOTE: *** allocated in the memory buffer, so the offset will be correct
  1270.     memset(memory + offset, 0, memorySize - offset);
  1271.  
  1272.     // return success
  1273.     return 0;
  1274. }
  1275.  
  1276. void doRelocations(ELF_t* elf, char* memory, int memorySize, int origin,
  1277.     const ELF_rel_type_t* rel_types, unsigned int rel_types_count)
  1278. {
  1279.     // apply the relocation records to the executable image
  1280.  
  1281.     // for each section...
  1282.     for (unsigned int i = 0; i<elf->sectionCount; ++i)
  1283.     {
  1284.         ELF_section_t* section = elf->sections + i;
  1285.  
  1286.         // if the section is not a REL or a RELA section, keep looking
  1287.         if ((section->header.sh_type != SHT_RELA) && (section->header.sh_type != SHT_REL)) continue;
  1288.  
  1289.         // is this a REL or a RELA section?
  1290.         int is_rela = (section->header.sh_type == SHT_RELA);
  1291.  
  1292.         // which section do these relocations apply to?
  1293.         int relocating_idx = section->header.sh_info;
  1294.  
  1295.         // get a pointer to that section
  1296.         ELF_section_t* relocating_section = elf->sections + relocating_idx;
  1297.  
  1298.         // if the section does not take space in the executable image, keep looking
  1299.         if (!(relocating_section->header.sh_flags & SHF_ALLOC)) continue;
  1300.  
  1301.         // the size of a single entity in the REL or RELA section
  1302.         int esize = section->header.sh_entsize;
  1303.  
  1304.         // work out how many records there are in this section
  1305.         int num = section->header.sh_size / esize;
  1306.  
  1307.         char* secdata = section->data;
  1308.         //assert(secdata);
  1309.  
  1310.         // for each relocation record...
  1311.         for (int j = 0; j<num; ++j, secdata += esize)
  1312.         {
  1313.             // get a pointer to the relocation record
  1314.             // NOTE: RELA is a superset of REL
  1315.             Elf32_Rela* rel = (Elf32_Rela*)secdata;
  1316.  
  1317.             // get a pointer to the symbol this relocation refers to
  1318.             ELF_symbol_t* sym = elf->symbols + ELF32_R_SYM(rel->r_info);
  1319.             // make sure the symbol has a resolved address
  1320.             //assert(sym->resolved);
  1321.  
  1322.             // get the address of the instruction to apply the relocation to
  1323.             unsigned int addr = rel->r_offset;
  1324.             if (elf->relocatable)
  1325.             {
  1326.                 // if the elf is relocatable, the address is relative to the section start
  1327.                 addr += relocating_section->header.sh_addr;
  1328.             }
  1329.  
  1330.             // find out what type of relocation to perform
  1331.             unsigned int type = ELF32_R_TYPE(rel->r_info);
  1332.  
  1333.             // if the type number is not recognised, skip over this one.
  1334.             // TODO: *** maybe report an error here?
  1335.             if ((type == 0) || (type >= rel_types_count)) continue;
  1336.  
  1337.             // get the offset of the insttuction in the executable image
  1338.             int offset = addr - origin;
  1339.  
  1340.             // check that this offset is within the executable image
  1341.             if (offset >= memorySize)
  1342.             {
  1343.                 // offset overflows the memory image, skip this relocation
  1344.                 //assert(0);
  1345.                 continue;
  1346.             }
  1347.  
  1348.             // get a pointer to the instruction to patch
  1349.             unsigned int* ptr = (unsigned int*)(memory + offset);
  1350.  
  1351.             // get the instruction into a uint and make sure it's endian correct for this machine
  1352.             unsigned int data = endian_word(elf->endian, *ptr);
  1353.  
  1354.             // extract the relocation information from the tables
  1355.             unsigned int mask = rel_types[type].mask;
  1356.             unsigned int shift = rel_types[type].shift;
  1357.             unsigned int position = rel_types[type].position;
  1358.  
  1359.             // if this is not a RELA relocation, the data in the instruction is the addend
  1360.             unsigned int inplace_addend = ((data & mask) >> position) << shift;
  1361.  
  1362.             // if this is a RELA relocation, use the addend, else use the data in the instruction
  1363.             unsigned int addend = is_rela ? rel->r_addend : inplace_addend;
  1364.  
  1365.             // if the relocation is a relative one (and SPU only has one: REL_SPU_REL16)
  1366.             // then subtract the PC from the addend making it PC relative.
  1367.             if (rel_types[type].relative)
  1368.             {
  1369.                 addend -= addr;
  1370.             }
  1371.  
  1372.             // reconstruct the final value to patch the instruction with
  1373.             unsigned int value = ((sym->vma + addend) >> shift) << position;
  1374.  
  1375.             // slot the value into the instruction masking off all the bits that need to stay
  1376.             data = (data & ~mask) | (value & mask);
  1377.  
  1378.             // write back the patched instruction in the correct endianness
  1379.             *ptr = endian_word(elf->endian, data);
  1380.         }
  1381.  
  1382.     }
  1383. }
  1384.  
  1385. int loadElfToMemory(unsigned char *memory, unsigned int size, unsigned int load_address, ELF_t *elf)
  1386. {
  1387.     unsigned int i;
  1388.  
  1389.     // load
  1390.     for (i = 0; i<elf->segmentCount; ++i)
  1391.     {
  1392.         Elf32_Addr p_vaddr;
  1393.         Elf32_Word p_filesz;
  1394.         Elf32_Word p_memsz;
  1395.         if (elf->segments[i].header.p_type != PT_LOAD) continue;
  1396.  
  1397.         p_vaddr = elf->segments[i].header.p_vaddr + load_address;
  1398.         p_filesz = elf->segments[i].header.p_filesz;
  1399.         p_memsz = elf->segments[i].header.p_memsz;
  1400.  
  1401.         if (p_vaddr + p_memsz > size) return -9; // ENOMEM
  1402.         if (p_filesz>0)
  1403.         {
  1404.             if (!elf->segments[i].data) return -11; // EINVAL
  1405.             memcpy(memory + p_vaddr, elf->segments[i].data, p_filesz);
  1406.         }
  1407.         if (p_filesz < p_memsz)
  1408.         {
  1409.             memset(memory + p_vaddr + p_filesz, 0, p_memsz - p_filesz);
  1410.         }
  1411.     }
  1412.  
  1413.     // GOT relocation
  1414.     if (load_address>0)
  1415.     {
  1416.         ELF_section_t *gotSection = findSection(elf, ".got");
  1417.         if (gotSection)
  1418.         {
  1419.             unsigned int seek_offset = gotSection->header.sh_offset;
  1420.             unsigned int entry_size = 0x1 << gotSection->header.sh_addralign;
  1421.             unsigned int num_entries = (gotSection->header.sh_size / entry_size) - 1;
  1422.             unsigned char *start = memory + load_address + seek_offset;
  1423.  
  1424.             for (i = 0; i<num_entries; i++)
  1425.             {
  1426.                 unsigned int *entry = (unsigned int *)start;
  1427.                 *entry = endian_word(elf->endian, endian_word(elf->endian, *entry) + load_address);
  1428.                 start += entry_size;
  1429.             }
  1430.         }
  1431.     }
  1432.  
  1433.     return 0;
  1434. }
  1435.  
  1436. void freeElf(ELF_t *elf)
  1437. {
  1438.     unsigned int i;
  1439.     if (!elf) return;
  1440.     if (elf->sections)
  1441.     {
  1442.         for (i = 0; i<elf->sectionCount; ++i)
  1443.         {
  1444.             if (elf->sections[i].data) free(elf->sections[i].data);
  1445.         }
  1446.         free(elf->sections);
  1447.     }
  1448.     if (elf->segments)
  1449.     {
  1450.         for (i = 0; i<elf->segmentCount; ++i)
  1451.         {
  1452.             if (elf->segments[i].pointer) free(elf->segments[i].pointer);
  1453.         }
  1454.         free(elf->segments);
  1455.     }
  1456.     if (elf->symbols)
  1457.         free(elf->symbols);
  1458.     free(elf);
  1459. }
  1460.  
  1461. // spu specific relocations.
  1462.  
  1463. static const ELF_rel_type_t spu_rel_types[] =
  1464. {
  1465.     /*relative, shift, size, position, mask */
  1466.     { 0, 0,   0,  0, 0x00000000 }, /* REL_SPU_NONE       0 */
  1467.     { 0, 4,  10, 14, 0x00ffc000 }, /* REL_SPU_ADDR10     1 */
  1468.     { 0, 2,  16,  7, 0x007fff80 }, /* REL_SPU_ADDR16     2 */
  1469.     { 0, 0,  16,  7, 0x007fff80 }, /* REL_SPU_ADDR16_LO  3 */
  1470.     { 0, 16, 16,  7, 0x007fff80 }, /* REL_SPU_ADDR16_HI  4 */
  1471.     { 0, 0,  18,  7, 0x01ffff80 }, /* REL_SPU_ADDR18     5 */
  1472.     { 0, 0,  32,  0, 0xffffffff }, /* REL_SPU_GLOB_DAT   6 */
  1473.     { 1, 2,  16,  7, 0x007fff80 }, /* REL_SPU_REL16      7 */
  1474.     { 0, 0,   7, 14, 0x001fc000 }, /* REL_SPU_IMM7       8 */
  1475.     { 0, 0,   8, 14, 0x003fc000 }, /* REL_SPU_IMM8       9 */
  1476.     { 0, 0,  10, 14, 0x00ffc000 }, /* REL_SPU_IM10      10 */
  1477. };
  1478.  
  1479. static const int spu_rel_types_count = sizeof(spu_rel_types) / sizeof(spu_rel_types[0]);
  1480.  
  1481. void spuDoRelocations(ELF_t *elf, char *memory, int memorySize, int origin)
  1482. {
  1483.     doRelocations(elf, memory, memorySize, origin, spu_rel_types, spu_rel_types_count);
  1484. }
  1485.  
  1486. static const char *_getStringTable(const Elf32_Ehdr *ehdr)
  1487. {
  1488.     const char *sectionHeaderStart = (const char*)ehdr + ehdr->e_shoff;
  1489.     const Elf32_Shdr *shstrtabHeader = (const Elf32_Shdr*)sectionHeaderStart + ehdr->e_shstrndx;
  1490.     return (const char*)ehdr + shstrtabHeader->sh_offset;
  1491. }
  1492.  
  1493. const char *findSectionInPlace(const char* memory, unsigned int /*size*/, const char *name, size_t *sectionSize)
  1494. {
  1495.     const Elf32_Ehdr *ehdr = (const Elf32_Ehdr*)memory;
  1496.  
  1497.     //first get the string section header
  1498.     const char *shstrtab = _getStringTable(ehdr);
  1499.  
  1500.     //find the section
  1501.     size_t sectionCount = ehdr->e_shnum;
  1502.     const char *sectionHeaderStart = (const char*)ehdr + ehdr->e_shoff;
  1503.     for (size_t i = 0; i<sectionCount; i++)
  1504.     {
  1505.         const Elf32_Shdr *sectionHeader = (const Elf32_Shdr *)sectionHeaderStart + i;
  1506.         const char *sectionName = shstrtab + sectionHeader->sh_name;
  1507.         if (!strcmp(name, sectionName))
  1508.         {
  1509.             *sectionSize = sectionHeader->sh_size;
  1510.             return (const char*)ehdr + sectionHeader->sh_offset;
  1511.         }
  1512.     }
  1513.     return NULL;
  1514. }
  1515.  
  1516. const char *findSymbolSectionInPlace(const char *memory, unsigned int /*size*/, size_t *symbolSize, size_t *symbolCount, const char **symbolstrtab)
  1517. {
  1518.     const Elf32_Ehdr *ehdr = (const Elf32_Ehdr*)memory;
  1519.  
  1520.     //find the section
  1521.     size_t sectionCount = ehdr->e_shnum;
  1522.     const char *sectionHeaderStart = (const char*)ehdr + ehdr->e_shoff;
  1523.     for (size_t i = 0; i<sectionCount; i++)
  1524.     {
  1525.         const Elf32_Shdr *sectionHeader = (const Elf32_Shdr *)sectionHeaderStart + i;
  1526.         if (sectionHeader->sh_type == SHT_SYMTAB)
  1527.         {
  1528.             *symbolSize = sectionHeader->sh_entsize;
  1529.             *symbolCount = sectionHeader->sh_size / sectionHeader->sh_entsize;
  1530.  
  1531.             const Elf32_Shdr *symbolStrHeader = (const Elf32_Shdr *)sectionHeaderStart + sectionHeader->sh_link;
  1532.             *symbolstrtab = (const char*)ehdr + symbolStrHeader->sh_offset;
  1533.             return (const char*)ehdr + sectionHeader->sh_offset;
  1534.         }
  1535.     }
  1536.     return NULL;
  1537. }
  1538.  
  1539. int lookupSymbolValueInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, const char *name)
  1540. {
  1541.     for (size_t i = 0; i<symbolCount; i++)
  1542.     {
  1543.         Elf32_Sym* elf_sym = (Elf32_Sym*)symbolSection;
  1544.  
  1545.         if (!strcmp(symbolstrtab + elf_sym->st_name, name))
  1546.         {
  1547.             return elf_sym->st_value;
  1548.         }
  1549.         symbolSection += symbolSize;
  1550.     }
  1551.     return -1;
  1552. }
  1553.  
  1554. const char *getSymbolByIndexInPlace(const char* symbolSection, size_t symbolSize, size_t symbolCount, const char *symbolstrtab, int index)
  1555. {
  1556.     //assert(index<(int)symbolCount);
  1557.     Elf32_Sym* elf_sym = (Elf32_Sym*)symbolSection + index;
  1558.     return symbolstrtab + elf_sym->st_name;
  1559. }
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.  
  1572.  
  1573.  
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579.  
  1580.  
  1581.  
  1582.  
  1583.  
  1584.  
  1585.  
  1586.  
  1587.  
  1588.  
  1589.  
  1590.  
  1591.  
  1592.  
  1593.  
  1594.  
  1595.  
  1596.  
  1597. //example:
  1598. void example_01()
  1599. {
  1600.     ELF_t* elf = readElfFromMemory((const char *)0x10000, 0x200);
  1601.     //ELF_t* elf = readElfFromFile("/dev_hdd0/tmp/mc_EBOOT.ELF");
  1602.  
  1603.  
  1604.     printf("elf->sectionCount: 0x%X\n", elf->sectionCount);
  1605.     for (int i = 0; i < elf->sectionCount; i++)
  1606.     {
  1607.         printf("elf->sections[%i].name: %s\n", i, elf->sections[i].name);
  1608.     }
  1609. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement