pubobj.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Copyright (C) 2004 by Alfons Hoogervorst.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <limits.h>
  22. #include <assert.h>
  23. /* Microsoft COFF definitions - inferred from data found in
  24. * "Windows 95 System Programming Secrets" by Matt Pietrek */
  25. #define IMAGE_SHORT_NAME_SIZE (8)
  26. #define FILE_MACHINE_INTEL_I386 (0x14C)
  27. #define FILE_CHARS_NO_RELOC (0x1)
  28. #define FILE_CHARS_EXECUTABLE (0x2)
  29. #define FILE_CHARS_DLL (0x2000)
  30. /* header */
  31. typedef struct {
  32. unsigned short machine;
  33. unsigned short sections;
  34. unsigned long time_stamp;
  35. unsigned long symbol_table_offset;
  36. unsigned long symbols;
  37. unsigned short optional_header_size;
  38. unsigned short characteristics;
  39. } image_file;
  40. /* symbol */
  41. typedef struct {
  42. union {
  43. unsigned char short_name[IMAGE_SHORT_NAME_SIZE];
  44. struct {
  45. unsigned long short_offset;
  46. unsigned long long_offset;
  47. } name;
  48. unsigned long long_name[2];
  49. } N;
  50. unsigned long value;
  51. short section_number;
  52. unsigned short type;
  53. unsigned char storage_class;
  54. unsigned char number_of_aux_symbols;
  55. } image_symbol;
  56. #define IMAGE_SYMBOL_SIZE ((sizeof (*((image_symbol *)(0))).N.short_name) + \
  57. (sizeof (*((image_symbol *)(0))).value) + \
  58. (sizeof (*((image_symbol *)(0))).section_number) + \
  59. (sizeof (*((image_symbol *)(0))).type) + \
  60. (sizeof (*((image_symbol *)(0))).storage_class) + \
  61. (sizeof (*((image_symbol *)(0))).number_of_aux_symbols))
  62. /***/
  63. /* XXX: Need to byte swap for big endian machines */
  64. #define READ_WORD(f, data) fread(&data, sizeof(data), 1, f)
  65. #define READ_DWORD(f, data) fread(&data, sizeof(data), 1, f)
  66. int main(int argc, char **argv)
  67. {
  68. assert(IMAGE_SYMBOL_SIZE == 18);
  69. fprintf(stderr, "pubobj - list public C declarations in Win32 COFF objects\n"
  70. "See http://claws-w32.sf.net\n");
  71. for (argc -= 1, argv = &argv[1]; argc; argc--, argv++) {
  72. FILE *fin;
  73. image_file imf;
  74. long n;
  75. unsigned long table_size = 0;
  76. char *string_table = NULL;
  77. if (NULL == (fin = fopen(argv[0], "rb")))
  78. continue;
  79. /* read informational data */
  80. READ_WORD(fin, imf.machine);
  81. READ_WORD(fin, imf.sections);
  82. READ_DWORD(fin, imf.time_stamp);
  83. READ_DWORD(fin, imf.symbol_table_offset);
  84. READ_DWORD(fin, imf.symbols);
  85. /* check for overflows, so we're limited to 2Gb files... */
  86. assert(imf.symbol_table_offset < (unsigned long) LONG_MAX);
  87. assert(imf.symbols < (unsigned long) LONG_MAX);
  88. /* seek to symbol table to read symbol table size */
  89. fseek(fin, (long) imf.symbol_table_offset, SEEK_SET);
  90. fseek(fin, (long) imf.symbols * IMAGE_SYMBOL_SIZE, SEEK_CUR);
  91. READ_DWORD(fin, table_size);
  92. /* table size dword is part of the table size */
  93. table_size -= 4;
  94. if (table_size) {
  95. /* allocate enough memory and read all symbols; they
  96. * are just ASCIIZ strings. */
  97. string_table = calloc(table_size, 1);
  98. fread(string_table, table_size, 1, fin);
  99. }
  100. /* good, iterate each symbol */
  101. fseek(fin, (long) imf.symbol_table_offset, SEEK_SET);
  102. n = 0;
  103. while (n < imf.symbols) {
  104. image_symbol ims;
  105. READ_DWORD(fin, ims.N.name.short_offset);
  106. READ_DWORD(fin, ims.N.name.long_offset);
  107. READ_DWORD(fin, ims.value);
  108. READ_WORD(fin, ims.section_number); /* XXX: signed */
  109. READ_WORD(fin, ims.type);
  110. ims.storage_class = fgetc(fin);
  111. ims.number_of_aux_symbols = fgetc(fin);
  112. /* external symbol */
  113. if (table_size && ims.storage_class == 2) {
  114. char safe_buf[IMAGE_SHORT_NAME_SIZE + 1];
  115. char *name;
  116. /*
  117. * 1) if type == 0x20, section_number != 0, it's a
  118. * function that's externally visible (non-static).
  119. *
  120. * 2) if type == 0x00, section_number == 0, value != 0,
  121. * it's a global variable. Note that since all
  122. * global variables are merged into one .data, this
  123. * would even include variables that are not defined
  124. * in this object
  125. */
  126. if ((ims.type == 0x20 && ims.section_number) ||
  127. (ims.type == 0x00 && ims.section_number == 0 && ims.value)) {
  128. if (ims.N.name.short_offset) {
  129. _snprintf(safe_buf, IMAGE_SHORT_NAME_SIZE + 1,
  130. "%s", ims.N.short_name);
  131. name = safe_buf;
  132. } else
  133. name = &string_table[ims.N.name.long_offset -
  134. sizeof(unsigned long)];
  135. /* We're only interested in _cdecls */
  136. if (*name == '_' && !strchr(name, '@'))
  137. printf("%s\n", name + 1);
  138. }
  139. }
  140. /* skip auxillary symbols (uninteresting junk) */
  141. if (ims.number_of_aux_symbols) {
  142. fseek(fin, ims.number_of_aux_symbols * IMAGE_SYMBOL_SIZE,
  143. SEEK_CUR);
  144. n += ims.number_of_aux_symbols;
  145. } else
  146. n++;
  147. }
  148. free(string_table);
  149. fclose(fin);
  150. }
  151. return 0;
  152. }