elf.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #pragma pack(1)
  5. #define EI_NIDENT 16
  6. typedef uint32_t ElfN_Addr;
  7. typedef uint32_t ElfN_Off;
  8. // https://www.man7.org/linux/man-pages/man5/elf.5.html
  9. struct ElfHeader {
  10. unsigned char e_ident[EI_NIDENT];
  11. uint16_t e_type;
  12. uint16_t e_machine;
  13. uint32_t e_version;
  14. ElfN_Addr e_entry;
  15. ElfN_Off e_phoff;
  16. ElfN_Off e_shoff;
  17. uint32_t e_flags;
  18. uint16_t e_ehsize;
  19. uint16_t e_phentsize;
  20. uint16_t e_phnum;
  21. uint16_t e_shentsize;
  22. uint16_t e_shnum;
  23. uint16_t e_shstrndx;
  24. };
  25. void show_elf_header (struct ElfHeader* eh) {
  26. printf("e_ident = %s\n", eh -> e_ident);
  27. printf("e_machine = %x\n", eh -> e_machine);
  28. printf("e_version = %x\n", eh -> e_version);
  29. printf("e_entry = %x\n", eh -> e_entry);
  30. printf("e_phoff = %x\n", eh -> e_phoff);
  31. printf("e_shoff = %x\n", eh -> e_shoff);
  32. printf("e_flags = %x\n", eh -> e_flags);
  33. printf("e_phentsize = %x\n", eh -> e_phentsize);
  34. return;
  35. }
  36. // mostly copy and paste
  37. struct Elf32_SectionHeader {
  38. uint32_t sh_name;
  39. uint32_t sh_type;
  40. uint32_t sh_flags;
  41. // Elf32_Addr sh_addr;
  42. uint32_t sh_addr;
  43. // Elf32_Off sh_offset;
  44. uint32_t sh_offset;
  45. uint32_t sh_size;
  46. uint32_t sh_link;
  47. uint32_t sh_info;
  48. uint32_t sh_addralign;
  49. uint32_t sh_entsize;
  50. };
  51. void show_section_header (struct Elf32_SectionHeader *sh) {
  52. if (sh == NULL) {
  53. printf("show_section_header: null ptr\n");
  54. return;
  55. }
  56. printf("sh_addr = %x\n", sh -> sh_addr);
  57. printf("sh_offset = %x\n", sh -> sh_offset);
  58. printf("sh_size = %x\n", sh -> sh_size);
  59. }
  60. // generic, load any binary file
  61. char *loadfile(const char *fname, unsigned int *s) {
  62. FILE *f = fopen(fname, "rb");
  63. unsigned int size = 0; // number of elements to buffer;
  64. unsigned int rcnt = 0; // number of char's read by fread(...)
  65. if (f == NULL) {
  66. perror("file handler is null ptr");
  67. return NULL;
  68. }
  69. // this method of determining file size works up to 2 GB.
  70. fseek(f, 0, SEEK_END);
  71. size = ftell(f);
  72. rewind(f);
  73. char *buf = (char*)malloc(sizeof(char) * size);
  74. if (buf == NULL) {
  75. perror("buf is null after malloc");
  76. free(buf);
  77. return NULL;
  78. }
  79. rcnt = fread(buf, sizeof(char), size, f);
  80. if (rcnt < size) {
  81. perror("read count < size");
  82. free(buf);
  83. return NULL;
  84. }
  85. fclose(f);
  86. *s = rcnt;
  87. return buf;
  88. }
  89. struct ELF32_SectionHeader*
  90. get_section_header(struct ElfHeader *eh, unsigned int i, unsigned int memsize) {
  91. struct Elf32_SectionHeader *sh;
  92. if (i > eh -> e_shnum) {
  93. perror("i exceeds eh -> e_shnum");
  94. return NULL;
  95. }
  96. char *mem = eh;
  97. unsigned int ith_offset = i * (eh -> e_shentsize);
  98. sh = mem + (eh -> e_shoff) + ith_offset;
  99. if (sh > mem+memsize) {
  100. printf("%x, %x\n", sh, memsize);
  101. perror("warning: potential segmentation fault ahead");
  102. }
  103. return sh;
  104. }
  105. #ifdef __ELF_STANDALONE__
  106. int main(int argc, char ** argv) {
  107. if (argc < 2) {
  108. printf("usage: program filename\n");
  109. return;
  110. }
  111. char *f = argv[1];
  112. unsigned int bufsize = 0;
  113. char *buffer = loadfile(f, &bufsize);
  114. struct ElfHeader *eh;
  115. eh = buffer;
  116. show_elf_header(eh);
  117. for (unsigned int i = 0; i < eh -> e_shnum; ++i) {
  118. printf("-- section header %.2i --\n", i);
  119. // struct Elf32_SectionHeader *sh;
  120. // unsigned int ith_offset = i * (eh -> e_shentsize);
  121. // printf("%x, %x\n", buffer+ith_offset, eh+ith_offset);
  122. struct Elf32_SectionHeader *sample;
  123. sample = get_section_header(eh, i, bufsize);
  124. // sh = buffer + (eh -> e_shoff) + ith_offset;
  125. show_section_header(sample);
  126. printf("-----------------------\n");
  127. }
  128. free(buffer);
  129. return 0;
  130. }
  131. #endif //__ELF_STANDALONE__