Added missing file.
[tinycc/k1w1.git] / win32 / tools / tiny_libmaker.c
blob95ace365be806bed3687ab6bd5213ef960371592
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>
12 #ifdef _WIN32
13 #include <io.h> /* for mktemp */
14 #endif
16 #include "../../config.h"
17 #include "../../elf.h"
19 #define ARMAG "!<arch>\n"
20 #define ARFMAG "`\n"
22 typedef struct ArHdr {
23 char ar_name[16];
24 char ar_date[12];
25 char ar_uid[6];
26 char ar_gid[6];
27 char ar_mode[8];
28 char ar_size[10];
29 char ar_fmag[2];
30 } ArHdr;
32 unsigned long le2belong(unsigned long ul) {
33 return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
34 ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
37 ArHdr arhdr = {
38 "/ ",
39 " ",
40 "0 ",
41 "0 ",
42 "0 ",
43 " ",
44 ARFMAG
47 ArHdr arhdro = {
48 " ",
49 " ",
50 "0 ",
51 "0 ",
52 "0 ",
53 " ",
54 ARFMAG
57 int main(int argc, char **argv)
59 FILE *fi, *fh, *fo;
60 ElfW(Ehdr) *ehdr;
61 ElfW(Shdr) *shdr;
62 ElfW(Sym) *sym;
63 int i, fsize, iarg;
64 char *buf, *shstr, *symtab = NULL, *strtab = NULL;
65 int symtabsize = 0, strtabsize = 0;
66 char *anames = NULL;
67 int *afpos = NULL;
68 int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
69 char afile[260], tfile[260], stmp[20];
72 strcpy(afile, "ar_test.a");
73 iarg = 1;
75 if (argc < 2)
77 printf("usage: tiny_libmaker [lib] file...\n");
78 return 1;
80 for (i=1; i<argc; i++) {
81 istrlen = strlen(argv[i]);
82 if (argv[i][istrlen-2] == '.') {
83 if(argv[i][istrlen-1] == 'a')
84 strcpy(afile, argv[i]);
85 else if(argv[i][istrlen-1] == 'o') {
86 iarg = i;
87 break;
92 strcpy(tfile, "./XXXXXX");
93 if (!mktemp(tfile) || (fo = fopen(tfile, "wb+")) == NULL)
95 fprintf(stderr, "Can't open temporary file %s\n", tfile);
96 return 2;
99 if ((fh = fopen(afile, "wb")) == NULL)
101 fprintf(stderr, "Can't open file %s \n", afile);
102 remove(tfile);
103 return 2;
106 funcmax = 250;
107 afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func
108 memcpy(&arhdro.ar_mode, "100666", 6);
110 //iarg = 1;
111 while (iarg < argc)
113 if (!strcmp(argv[iarg], "rcs")) {
114 iarg++;
115 continue;
117 if ((fi = fopen(argv[iarg], "rb")) == NULL)
119 fprintf(stderr, "Can't open file %s \n", argv[iarg]);
120 remove(tfile);
121 return 2;
123 fseek(fi, 0, SEEK_END);
124 fsize = ftell(fi);
125 fseek(fi, 0, SEEK_SET);
126 buf = malloc(fsize + 1);
127 fread(buf, fsize, 1, fi);
128 fclose(fi);
130 //printf("%s:\n", argv[iarg]);
131 // elf header
132 ehdr = (ElfW(Ehdr) *)buf;
133 if (ehdr->e_ident[4] != TCC_ELFCLASS)
135 fprintf(stderr, "Unsupported Elf Class: %s\n", argv[iarg]);
136 remove(tfile);
137 return 2;
140 shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
141 shstr = (char *)(buf + shdr->sh_offset);
142 for (i = 0; i < ehdr->e_shnum; i++)
144 shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
145 if (!shdr->sh_offset) continue;
146 if (shdr->sh_type == SHT_SYMTAB)
148 symtab = (char *)(buf + shdr->sh_offset);
149 symtabsize = shdr->sh_size;
151 if (shdr->sh_type == SHT_STRTAB)
153 if (!strcmp(shstr + shdr->sh_name, ".strtab"))
155 strtab = (char *)(buf + shdr->sh_offset);
156 strtabsize = shdr->sh_size;
161 if (symtab && symtabsize)
163 int nsym = symtabsize / sizeof(ElfW(Sym));
164 //printf("symtab: info size shndx name\n");
165 for (i = 1; i < nsym; i++)
167 sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
168 if (sym->st_shndx &&
169 (sym->st_info == 0x10
170 || sym->st_info == 0x11
171 || sym->st_info == 0x12
172 )) {
173 //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
174 istrlen = strlen(strtab + sym->st_name)+1;
175 anames = realloc(anames, strpos+istrlen);
176 strcpy(anames + strpos, strtab + sym->st_name);
177 strpos += istrlen;
178 if (++funccnt >= funcmax) {
179 funcmax += 250;
180 afpos = realloc(afpos, funcmax * sizeof *afpos); // 250 func more
182 afpos[funccnt] = fpos;
186 memset(&arhdro.ar_name, ' ', sizeof(arhdr.ar_name));
187 strcpy(arhdro.ar_name, argv[iarg]);
188 arhdro.ar_name[strlen(argv[iarg])] = '/';
189 sprintf(stmp, "%-10d", fsize);
190 memcpy(&arhdro.ar_size, stmp, 10);
191 fwrite(&arhdro, sizeof(arhdro), 1, fo);
192 fwrite(buf, fsize, 1, fo);
193 free(buf);
194 iarg++;
195 fpos += (fsize + sizeof(arhdro));
197 hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
198 if ((hofs & 1)) { // align
199 hofs++;
200 fpos = 1;
201 } else fpos = 0;
202 // write header
203 fwrite("!<arch>\n", 8, 1, fh);
204 sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
205 memcpy(&arhdr.ar_size, stmp, 10);
206 fwrite(&arhdr, sizeof(arhdr), 1, fh);
207 afpos[0] = le2belong(funccnt);
208 for (i=1; i<=funccnt; i++) {
209 afpos[i] = le2belong(afpos[i] + hofs);
211 fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
212 fwrite(anames, strpos, 1, fh);
213 if (fpos) fwrite("", 1, 1, fh);
214 // write objects
215 fseek(fo, 0, SEEK_END);
216 fsize = ftell(fo);
217 fseek(fo, 0, SEEK_SET);
218 buf = malloc(fsize + 1);
219 fread(buf, fsize, 1, fo);
220 fclose(fo);
221 fwrite(buf, fsize, 1, fh);
222 fclose(fh);
223 free(buf);
224 if (anames)
225 free(anames);
226 if (afpos)
227 free(afpos);
228 remove(tfile);
229 return 0;