tiny_libmaker.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /*
  2. * This program is for making libtcc1.a without ar
  3. * tiny_libmaker - tiny elf lib maker
  4. * usage: tiny_libmaker [lib] files...
  5. * Copyright (c) 2007 Timppa
  6. *
  7. * This program is free software but WITHOUT ANY WARRANTY
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #ifdef _WIN32
  13. #include <io.h> /* for mktemp */
  14. #endif
  15. /* #include "ar-elf.h" */
  16. /* "ar-elf.h" */
  17. /* ELF_v1.2.pdf */
  18. typedef unsigned short int Elf32_Half;
  19. typedef int Elf32_Sword;
  20. typedef unsigned int Elf32_Word;
  21. typedef unsigned int Elf32_Addr;
  22. typedef unsigned int Elf32_Off;
  23. typedef unsigned short int Elf32_Section;
  24. #define EI_NIDENT 16
  25. typedef struct {
  26. unsigned char e_ident[EI_NIDENT];
  27. Elf32_Half e_type;
  28. Elf32_Half e_machine;
  29. Elf32_Word e_version;
  30. Elf32_Addr e_entry;
  31. Elf32_Off e_phoff;
  32. Elf32_Off e_shoff;
  33. Elf32_Word e_flags;
  34. Elf32_Half e_ehsize;
  35. Elf32_Half e_phentsize;
  36. Elf32_Half e_phnum;
  37. Elf32_Half e_shentsize;
  38. Elf32_Half e_shnum;
  39. Elf32_Half e_shstrndx;
  40. } Elf32_Ehdr;
  41. typedef struct {
  42. Elf32_Word sh_name;
  43. Elf32_Word sh_type;
  44. Elf32_Word sh_flags;
  45. Elf32_Addr sh_addr;
  46. Elf32_Off sh_offset;
  47. Elf32_Word sh_size;
  48. Elf32_Word sh_link;
  49. Elf32_Word sh_info;
  50. Elf32_Word sh_addralign;
  51. Elf32_Word sh_entsize;
  52. } Elf32_Shdr;
  53. #define SHT_NULL 0
  54. #define SHT_PROGBITS 1
  55. #define SHT_SYMTAB 2
  56. #define SHT_STRTAB 3
  57. #define SHT_RELA 4
  58. #define SHT_HASH 5
  59. #define SHT_DYNAMIC 6
  60. #define SHT_NOTE 7
  61. #define SHT_NOBITS 8
  62. #define SHT_REL 9
  63. #define SHT_SHLIB 10
  64. #define SHT_DYNSYM 11
  65. typedef struct {
  66. Elf32_Word st_name;
  67. Elf32_Addr st_value;
  68. Elf32_Word st_size;
  69. unsigned char st_info;
  70. unsigned char st_other;
  71. Elf32_Half st_shndx;
  72. } Elf32_Sym;
  73. #define ELF32_ST_BIND(i) ((i)>>4)
  74. #define ELF32_ST_TYPE(i) ((i)&0xf)
  75. #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
  76. #define STT_NOTYPE 0
  77. #define STT_OBJECT 1
  78. #define STT_FUNC 2
  79. #define STT_SECTION 3
  80. #define STT_FILE 4
  81. #define STT_LOPROC 13
  82. #define STT_HIPROC 15
  83. #define STB_LOCAL 0
  84. #define STB_GLOBAL 1
  85. #define STB_WEAK 2
  86. #define STB_LOPROC 13
  87. #define STB_HIPROC 15
  88. typedef struct {
  89. Elf32_Word p_type;
  90. Elf32_Off p_offset;
  91. Elf32_Addr p_vaddr;
  92. Elf32_Addr p_paddr;
  93. Elf32_Word p_filesz;
  94. Elf32_Word p_memsz;
  95. Elf32_Word p_flags;
  96. Elf32_Word p_align;
  97. } Elf32_Phdr;
  98. /* "ar-elf.h" ends */
  99. #define ARMAG "!<arch>\n"
  100. #define ARFMAG "`\n"
  101. typedef struct ArHdr {
  102. char ar_name[16];
  103. char ar_date[12];
  104. char ar_uid[6];
  105. char ar_gid[6];
  106. char ar_mode[8];
  107. char ar_size[10];
  108. char ar_fmag[2];
  109. } ArHdr;
  110. unsigned long le2belong(unsigned long ul) {
  111. return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
  112. ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
  113. }
  114. ArHdr arhdr = {
  115. "/ ",
  116. " ",
  117. "0 ",
  118. "0 ",
  119. "0 ",
  120. " ",
  121. ARFMAG
  122. };
  123. ArHdr arhdro = {
  124. " ",
  125. " ",
  126. "0 ",
  127. "0 ",
  128. "0 ",
  129. " ",
  130. ARFMAG
  131. };
  132. int main(int argc, char **argv)
  133. {
  134. FILE *fi, *fh, *fo;
  135. Elf32_Ehdr *ehdr;
  136. Elf32_Shdr *shdr;
  137. Elf32_Sym *sym;
  138. int i, fsize, iarg;
  139. char *buf, *shstr, *symtab = NULL, *strtab = NULL;
  140. int symtabsize = 0, strtabsize = 0;
  141. char *anames = NULL;
  142. int *afpos = NULL;
  143. int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
  144. char afile[260], tfile[260], stmp[20];
  145. strcpy(afile, "ar_test.a");
  146. iarg = 1;
  147. if (argc < 2)
  148. {
  149. printf("usage: tiny_libmaker [lib] file...\n");
  150. return 1;
  151. }
  152. for (i=1; i<argc; i++) {
  153. istrlen = strlen(argv[i]);
  154. if (argv[i][istrlen-2] == '.') {
  155. if(argv[i][istrlen-1] == 'a')
  156. strcpy(afile, argv[i]);
  157. else if(argv[i][istrlen-1] == 'o') {
  158. iarg = i;
  159. break;
  160. }
  161. }
  162. }
  163. strcpy(tfile, "./XXXXXX");
  164. if (!mktemp(tfile) || (fo = fopen(tfile, "wb+")) == NULL)
  165. {
  166. fprintf(stderr, "Can't open temporary file %s\n", tfile);
  167. return 2;
  168. }
  169. if ((fh = fopen(afile, "wb")) == NULL)
  170. {
  171. fprintf(stderr, "Can't open file %s \n", afile);
  172. remove(tfile);
  173. return 2;
  174. }
  175. funcmax = 250;
  176. afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func
  177. memcpy(&arhdro.ar_mode, "100666", 6);
  178. //iarg = 1;
  179. while (iarg < argc)
  180. {
  181. if (!strcmp(argv[iarg], "rcs")) {
  182. iarg++;
  183. continue;
  184. }
  185. if ((fi = fopen(argv[iarg], "rb")) == NULL)
  186. {
  187. fprintf(stderr, "Can't open file %s \n", argv[iarg]);
  188. remove(tfile);
  189. return 2;
  190. }
  191. fseek(fi, 0, SEEK_END);
  192. fsize = ftell(fi);
  193. fseek(fi, 0, SEEK_SET);
  194. buf = malloc(fsize + 1);
  195. fread(buf, fsize, 1, fi);
  196. fclose(fi);
  197. printf("%s:\n", argv[iarg]);
  198. // elf header
  199. ehdr = (Elf32_Ehdr *)buf;
  200. shdr = (Elf32_Shdr *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
  201. shstr = (char *)(buf + shdr->sh_offset);
  202. for (i = 0; i < ehdr->e_shnum; i++)
  203. {
  204. shdr = (Elf32_Shdr *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
  205. if (!shdr->sh_offset) continue;
  206. if (shdr->sh_type == SHT_SYMTAB)
  207. {
  208. symtab = (char *)(buf + shdr->sh_offset);
  209. symtabsize = shdr->sh_size;
  210. }
  211. if (shdr->sh_type == SHT_STRTAB)
  212. {
  213. if (!strcmp(shstr + shdr->sh_name, ".strtab"))
  214. {
  215. strtab = (char *)(buf + shdr->sh_offset);
  216. strtabsize = shdr->sh_size;
  217. }
  218. }
  219. }
  220. if (symtab && symtabsize)
  221. {
  222. int nsym = symtabsize / sizeof(Elf32_Sym);
  223. //printf("symtab: info size shndx name\n");
  224. for (i = 1; i < nsym; i++)
  225. {
  226. sym = (Elf32_Sym *) (symtab + i * sizeof(Elf32_Sym));
  227. if (sym->st_shndx && (sym->st_info == 0x11 || sym->st_info == 0x12)) {
  228. //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
  229. istrlen = strlen(strtab + sym->st_name)+1;
  230. anames = realloc(anames, strpos+istrlen);
  231. strcpy(anames + strpos, strtab + sym->st_name);
  232. strpos += istrlen;
  233. if (++funccnt >= funcmax) {
  234. funcmax += 250;
  235. afpos = realloc(afpos, funcmax * sizeof *afpos); // 250 func more
  236. }
  237. afpos[funccnt] = fpos;
  238. }
  239. }
  240. }
  241. memset(&arhdro.ar_name, ' ', sizeof(arhdr.ar_name));
  242. strcpy(arhdro.ar_name, argv[iarg]);
  243. arhdro.ar_name[strlen(argv[iarg])] = '/';
  244. sprintf(stmp, "%-10d", fsize);
  245. memcpy(&arhdro.ar_size, stmp, 10);
  246. fwrite(&arhdro, sizeof(arhdro), 1, fo);
  247. fwrite(buf, fsize, 1, fo);
  248. free(buf);
  249. iarg++;
  250. fpos += (fsize + sizeof(arhdro));
  251. }
  252. hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
  253. if ((hofs & 1)) { // align
  254. hofs++;
  255. fpos = 1;
  256. } else fpos = 0;
  257. // write header
  258. fwrite("!<arch>\n", 8, 1, fh);
  259. sprintf(stmp, "%-10d", strpos + (funccnt+1) * sizeof(int));
  260. memcpy(&arhdr.ar_size, stmp, 10);
  261. fwrite(&arhdr, sizeof(arhdr), 1, fh);
  262. afpos[0] = le2belong(funccnt);
  263. for (i=1; i<=funccnt; i++) {
  264. afpos[i] = le2belong(afpos[i] + hofs);
  265. }
  266. fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
  267. fwrite(anames, strpos, 1, fh);
  268. if (fpos) fwrite("", 1, 1, fh);
  269. // write objects
  270. fseek(fo, 0, SEEK_END);
  271. fsize = ftell(fo);
  272. fseek(fo, 0, SEEK_SET);
  273. buf = malloc(fsize + 1);
  274. fread(buf, fsize, 1, fo);
  275. fclose(fo);
  276. fwrite(buf, fsize, 1, fh);
  277. fclose(fh);
  278. free(buf);
  279. if (anames)
  280. free(anames);
  281. if (afpos)
  282. free(afpos);
  283. remove(tfile);
  284. return 0;
  285. }