Checkin tiny_libmaker (ar replacement) by Timovj Lahde
[tinycc/miki.git] / win32 / tools / tiny_libmaker.c
blobefda78adc43b11ac010fdf96eb735954ecfdb73a
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
7 * This program is free software but WITHOUT ANY WARRANTY
8 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
13 /* #include "ar-elf.h" */
14 /* "ar-elf.h" */
15 /* ELF_v1.2.pdf */
16 typedef unsigned short int Elf32_Half;
17 typedef int Elf32_Sword;
18 typedef unsigned int Elf32_Word;
19 typedef unsigned int Elf32_Addr;
20 typedef unsigned int Elf32_Off;
21 typedef unsigned short int Elf32_Section;
23 #define EI_NIDENT 16
24 typedef struct {
25 unsigned char e_ident[EI_NIDENT];
26 Elf32_Half e_type;
27 Elf32_Half e_machine;
28 Elf32_Word e_version;
29 Elf32_Addr e_entry;
30 Elf32_Off e_phoff;
31 Elf32_Off e_shoff;
32 Elf32_Word e_flags;
33 Elf32_Half e_ehsize;
34 Elf32_Half e_phentsize;
35 Elf32_Half e_phnum;
36 Elf32_Half e_shentsize;
37 Elf32_Half e_shnum;
38 Elf32_Half e_shstrndx;
39 } 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;
54 #define SHT_NULL 0
55 #define SHT_PROGBITS 1
56 #define SHT_SYMTAB 2
57 #define SHT_STRTAB 3
58 #define SHT_RELA 4
59 #define SHT_HASH 5
60 #define SHT_DYNAMIC 6
61 #define SHT_NOTE 7
62 #define SHT_NOBITS 8
63 #define SHT_REL 9
64 #define SHT_SHLIB 10
65 #define SHT_DYNSYM 11
67 typedef struct {
68 Elf32_Word st_name;
69 Elf32_Addr st_value;
70 Elf32_Word st_size;
71 unsigned char st_info;
72 unsigned char st_other;
73 Elf32_Half st_shndx;
74 } Elf32_Sym;
76 #define ELF32_ST_BIND(i) ((i)>>4)
77 #define ELF32_ST_TYPE(i) ((i)&0xf)
78 #define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
80 #define STT_NOTYPE 0
81 #define STT_OBJECT 1
82 #define STT_FUNC 2
83 #define STT_SECTION 3
84 #define STT_FILE 4
85 #define STT_LOPROC 13
86 #define STT_HIPROC 15
88 #define STB_LOCAL 0
89 #define STB_GLOBAL 1
90 #define STB_WEAK 2
91 #define STB_LOPROC 13
92 #define STB_HIPROC 15
94 typedef struct {
95 Elf32_Word p_type;
96 Elf32_Off p_offset;
97 Elf32_Addr p_vaddr;
98 Elf32_Addr p_paddr;
99 Elf32_Word p_filesz;
100 Elf32_Word p_memsz;
101 Elf32_Word p_flags;
102 Elf32_Word p_align;
103 } Elf32_Phdr;
104 /* "ar-elf.h" ends */
106 #define ARMAG "!<arch>\n"
107 #define ARFMAG "`\n"
109 typedef struct ArHdr {
110 char ar_name[16];
111 char ar_date[12];
112 char ar_uid[6];
113 char ar_gid[6];
114 char ar_mode[8];
115 char ar_size[10];
116 char ar_fmag[2];
117 } ArHdr;
120 unsigned long le2belong(unsigned long ul) {
121 return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
122 ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
125 ArHdr arhdr = {
126 "/ ",
127 " ",
128 "0 ",
129 "0 ",
130 "0 ",
131 " ",
132 ARFMAG
135 ArHdr arhdro = {
136 " ",
137 " ",
138 "0 ",
139 "0 ",
140 "0 ",
141 " ",
142 ARFMAG
145 int main(int argc, char **argv)
147 FILE *fi, *fh, *fo;
148 Elf32_Ehdr *ehdr;
149 Elf32_Shdr *shdr;
150 Elf32_Sym *sym;
151 int i, fsize, iarg;
152 char *buf, *shstr, *symtab = NULL, *strtab = NULL;
153 int symtabsize = 0, strtabsize = 0;
154 char *anames = NULL;
155 int *afpos = NULL;
156 int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
157 char afile[260], tfile[260], stmp[20];
160 strcpy(afile, "ar_test.a");
161 iarg = 1;
163 if (argc < 2)
165 printf("usage: tiny_libmaker [lib] file...\n");
166 return 1;
168 for (i=1; i<argc; i++) {
169 istrlen = strlen(argv[i]);
170 if (argv[i][istrlen-2] == '.') {
171 if(argv[i][istrlen-1] == 'a')
172 strcpy(afile, argv[i]);
173 else if(argv[i][istrlen-1] == 'o') {
174 iarg = i;
175 break;
180 //tfile[0] = '.'; tfile[1] = '/';
181 //if (tmpnam(&tfile[2])) {
182 strcpy(tfile, "./XXXXXX");
183 if (mktemp(tfile))
185 if ((fo = fopen(tfile, "wb+")) == NULL)
187 fprintf(stderr, "Can't open file %s \n", tfile);
188 return 2;
193 if ((fo = tmpfile()) == NULL)
195 fprintf(stderr, "Can't open temporary file \n");
196 return 2;
199 if ((fh = fopen(afile, "wb")) == NULL)
201 fprintf(stderr, "Can't open file %s \n", afile);
202 remove(tfile);
203 return 2;
206 funcmax = 1000;
207 afpos = realloc(NULL, funcmax); // 250 func
208 memcpy(&arhdro.ar_mode, "100666", 6);
210 //iarg = 1;
211 while (iarg < argc)
213 if (!strcmp(argv[iarg], "rcs")) {
214 iarg++;
215 continue;
217 if ((fi = fopen(argv[iarg], "rb")) == NULL)
219 fprintf(stderr, "Can't open file %s \n", argv[iarg]);
220 remove(tfile);
221 return 2;
223 fseek(fi, 0, SEEK_END);
224 fsize = ftell(fi);
225 fseek(fi, 0, SEEK_SET);
226 buf = malloc(fsize + 1);
227 fread(buf, fsize, 1, fi);
228 fclose(fi);
230 printf("%s:\n", argv[iarg]);
231 // elf header
232 ehdr = (Elf32_Ehdr *)buf;
233 shdr = (Elf32_Shdr *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
234 shstr = (char *)(buf + shdr->sh_offset);
235 for (i = 0; i < ehdr->e_shnum; i++)
237 shdr = (Elf32_Shdr *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
238 if (!shdr->sh_offset) continue;
239 if (shdr->sh_type == SHT_SYMTAB)
241 symtab = (char *)(buf + shdr->sh_offset);
242 symtabsize = shdr->sh_size;
244 if (shdr->sh_type == SHT_STRTAB)
246 if (!strcmp(shstr + shdr->sh_name, ".strtab"))
248 strtab = (char *)(buf + shdr->sh_offset);
249 strtabsize = shdr->sh_size;
254 if (symtab && symtabsize)
256 int nsym = symtabsize / sizeof(Elf32_Sym);
257 //printf("symtab: info size shndx name\n");
258 for (i = 1; i < nsym; i++)
260 sym = (Elf32_Sym *) (symtab + i * sizeof(Elf32_Sym));
261 if (sym->st_shndx && (sym->st_info == 0x11 || sym->st_info == 0x12)) {
262 //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
263 istrlen = strlen(strtab + sym->st_name)+1;
264 anames = realloc(anames, strpos+istrlen);
265 strcpy(anames + strpos, strtab + sym->st_name);
266 strpos += istrlen;
267 if (funccnt >= funcmax) {
268 afpos = realloc(NULL, funcmax+1000); // 250 func more
269 funcmax += 1000;
271 afpos[++funccnt] = fpos;
275 memset(&arhdro.ar_name, ' ', sizeof(arhdr.ar_name));
276 strcpy(arhdro.ar_name, argv[iarg]);
277 arhdro.ar_name[strlen(argv[iarg])] = '/';
278 sprintf(stmp, "%-10d", fsize);
279 memcpy(&arhdro.ar_size, stmp, 10);
280 fwrite(&arhdro, sizeof(arhdro), 1, fo);
281 fwrite(buf, fsize, 1, fo);
282 free(buf);
283 iarg++;
284 fpos += (fsize + sizeof(arhdro));
286 hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
287 if ((hofs & 1)) { // align
288 hofs++;
289 fpos = 1;
290 } else fpos = 0;
291 // write header
292 fwrite("!<arch>\n", 8, 1, fh);
293 sprintf(stmp, "%-10d", strpos + (funccnt+1) * sizeof(int));
294 memcpy(&arhdr.ar_size, stmp, 10);
295 fwrite(&arhdr, sizeof(arhdr), 1, fh);
296 afpos[0] = le2belong(funccnt);
297 for (i=1; i<=funccnt; i++) {
298 afpos[i] = le2belong(afpos[i] + hofs);
300 fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
301 fwrite(anames, strpos, 1, fh);
302 if (fpos) fwrite("", 1, 1, fh);
303 // write objects
304 fseek(fo, 0, SEEK_END);
305 fsize = ftell(fo);
306 fseek(fo, 0, SEEK_SET);
307 buf = malloc(fsize + 1);
308 fread(buf, fsize, 1, fo);
309 fclose(fo);
310 fwrite(buf, fsize, 1, fh);
311 fclose(fh);
312 free(buf);
313 if (anames)
314 free(anames);
315 if (afpos)
316 free(afpos);
317 remove(tfile);
318 return 0;