|
|
1.1 root 1: /* Copyright 1989 by AT&T Bell Laboratories */
2: /* linkdata.c -- group files into the text segment of a .o file */
3:
4: #define SYMBOL "_datalist"
5: #define END_SYMBOL "_endmo"
6:
7: #include <stdio.h>
8: #include <a.out.h>
9: #include <assert.h>
10: #include <sys/types.h>
11: #include <sys/stat.h>
12: #include "tags.h"
13:
14: #define LONG (sizeof(long))
15: #define align(x) (((x) + (LONG - 1)) & ~(LONG - 1))
16:
17: #ifdef SPARC
18: #define relocation_info reloc_info_sparc
19: #endif
20:
21: #define RELINFO_SZ (sizeof (struct relocation_info))
22:
23: struct relocation_info rconst, *rel;
24: struct nlist nlconst, *nl;
25:
26: struct str_table { /* The string table buffer. */
27: int len; /* length including this word */
28: char strs[4];
29: } *str_tbl;
30: char *str_ptr; /* the next location in the string table. */
31:
32: /* add_name:
33: * Extract the structure name from the file name and add it to the string table
34: * buffer (with an initial "_").
35: */
36: void add_name (file)
37: char *file;
38: {
39: register char *p, *begin;
40: int len, res;
41:
42: /* find the beginning of the file name. */
43: for (p = begin = file; *p; p++) {
44: if (*p == '/')
45: begin = p+1;
46: }
47:
48: /* find the ".mo" */
49: for (p = begin, len = 0; *p && (*p != '.'); p++, len++)
50: continue;
51:
52: *str_ptr++ = '_';
53: strncpy(str_ptr, begin, len);
54: str_ptr += len;
55: *str_ptr++ = '\0';
56: str_tbl->len += (len+2);
57: }
58:
59: void die(s)
60: char *s;
61: {
62: perror(s);
63: exit(1);
64: }
65:
66: extern long *malloc(); /* wrong but convenient */
67:
68:
69: /* link:
70: * append the code from file to linked code. pc is the relative starting address,
71: * last = 1, if this is the last file to link.
72: */
73: int link (file, pc, last)
74: char *file; long pc; int last;
75: {
76: int fd;
77: long i, len, n, nbytes;
78: char *s;
79: struct stat st;
80: static int bufsize = 0;
81: static long *buf;
82:
83: if ((fd = open(file, 0)) == -1) {
84: char buf[64];
85: sprintf(buf, "open: %s", file);
86: die(buf);
87: }
88: if (fstat(fd, &st) == -1)
89: die("stat");
90:
91: n = st.st_size;
92: len = strlen(file);
93: nbytes = align(n) + align(len) + 6 * LONG;
94:
95: if (n + len + 40 > bufsize) {
96: bufsize = n + len + 4096;
97: if (buf != NULL)
98: free(buf);
99: buf = malloc(bufsize);
100: if (buf == NULL)
101: die("malloc(buf)");
102: }
103:
104: /* initialize the header record and add its fields to the list of
105: * relocatable addresses.
106: */
107: buf[0] = mak_desc(3, tag_record);
108: #ifdef SPARC
109: #define REL(addr, addend) \
110: (*rel = rconst, rel->r_addend = (addend), (rel++)->r_address = (addr))
111:
112: buf[1] = 0;
113: REL(pc + LONG, pc + 5 * LONG);
114: buf[2] = 0;
115: REL(pc + 2 * LONG, pc + 6 * LONG + align(len));
116: if (last)
117: buf[3] = 1; /* either ML 0 */
118: else {
119: buf[3] = 0;
120: REL(pc + 3 * LONG, pc + nbytes + LONG);
121: }
122: #else
123:
124: #define REL(addr) (*rel = rconst, (rel++)->r_address = (addr))
125:
126: buf[1] = pc + 5 * LONG; /* address of file name */
127: REL(pc + LONG);
128: buf[2] = buf[1] + LONG + align(len); /* address of code */
129: REL(pc + 2 * LONG);
130: if (last)
131: buf[3] = 1; /* either ML 0 */
132: else {
133: buf[3] = pc + nbytes + LONG; /* or the address of next module */
134: REL(pc + 3 * LONG);
135: }
136: #endif
137:
138: buf[4] = mak_desc(len, tag_string); /* tag for file name */
139: strcpy(&buf[5], file);
140: s = ((char *) &buf[5]) + len;
141: for (i = align(len); i > len; i--)
142: *s++ = 0;
143:
144: *((long *) s) = mak_desc(n, tag_string); /* tag for code */
145: s += LONG;
146:
147: /* record this structure in the symbol and string tables */
148: *nl = nlconst;
149: nl->n_un.n_strx = str_tbl->len;
150: nl->n_value = pc + 6*LONG + align(len); /* relative code address */
151: nl++;
152: add_name(file);
153:
154: if (read(fd, s, n) != n)
155: die("read");
156: s += n;
157: for (i = align(n); i > n; i--)
158: *s++ = 0;
159:
160: if (close(fd) == -1)
161: die("close");
162:
163: assert(s - nbytes == (char *) buf);
164: write(1, buf, nbytes);
165: return nbytes;
166: }
167:
168: int main(argc, argv)
169: int argc;
170: char *argv[];
171: {
172: long pc = 0;
173: struct exec exec;
174: struct nlist *nlbase;
175: struct relocation_info *relbase;
176: int i, sz;
177:
178: /* allocate space for the string table */
179: sz = strlen(SYMBOL)+strlen(END_SYMBOL)+LONG+1;
180: for (i = 1; i < argc; i++)
181: sz += strlen(argv[i])+2;
182: str_tbl = (struct str_table *) malloc(align(sz));
183: if ((long)str_tbl == NULL)
184: die("malloc(str_tbl)");
185:
186: /* initialize the string table buffer with the "_datalist" string */
187: str_ptr = str_tbl->strs;
188: strcpy(str_ptr, SYMBOL);
189: str_ptr += strlen(SYMBOL)+1;
190: str_tbl->len = LONG + strlen(SYMBOL)+1;
191:
192: /* Allocate space for nlist and reloc info buffers */
193: nl = nlbase = (struct nlist *) malloc((argc+1) * sizeof(struct nlist));
194: if ((long) nl == NULL)
195: die("malloc(nl)");
196: rel = relbase = (struct relocation_info *) malloc(3 * argc * RELINFO_SZ);
197: if ((long) rel == NULL)
198: die("malloc(rel)");
199:
200: /* build a nlist constant to initialize from, and initialize the datalist entry. */
201: nlconst.n_other = 0;
202: nlconst.n_desc = 0;
203: if (argc > 1) {
204: nlconst.n_type = N_EXT | N_TEXT; /* global in text area */
205: nlconst.n_value = 4; /* for datalist */
206: }
207: else {
208: /* Actually, there is only one symbol (ie., datalist) */
209: nlconst.n_type = N_EXT | N_ABS;
210: nlconst.n_value = 1; /* ML zero */
211: }
212: *nl = nlconst; (nl++)->n_un.n_strx = 4; /* datalist, first string table entry */
213:
214: /* build a relocation constant to assign from */
215: #ifdef SPARC
216: rconst.r_address = 0;
217: rconst.r_index = N_TEXT;
218: rconst.r_extern = 0; /* r_index is the segment (text) */
219: rconst.r_type = RELOC_32;
220: rconst.r_addend = 0;
221: #else
222: rconst.r_address = 0;
223: rconst.r_symbolnum = 4; /* i don't know why this works. magic? */
224: rconst.r_pcrel = 0;
225: rconst.r_length = 2; /* long */
226: rconst.r_extern = 0;
227: #endif
228:
229: /* initialize the header, we fill in the text size info later */
230: #ifdef M68
231: exec.a_machtype = M_68020;
232: #endif
233: #ifdef SPARC
234: exec.a_dynamic = 0;
235: exec.a_machtype = M_SPARC;
236: exec.a_toolversion = 1;
237: #endif
238: exec.a_magic = OMAGIC;
239: exec.a_data = 0;
240: exec.a_bss = 0;
241: /* one per mo plus "datalist" and "_endmo" */
242: exec.a_syms = (argc+1) * sizeof(struct nlist);
243: exec.a_entry = 0;
244: exec.a_drsize = 0;
245: if (write(1, &exec, sizeof exec) == -1)
246: die("write");
247:
248: for (i=1; i<argc; i++)
249: pc += link(argv[i], pc, i==argc-1);
250:
251: exec.a_text = pc;
252: exec.a_trsize = (rel - relbase) * RELINFO_SZ;
253:
254: if (write(1, relbase, exec.a_trsize) == -1)
255: die("write(rel)");
256:
257: /* Add "_endmo" to the name list and string table */
258: *nl = nlconst;
259: nl->n_un.n_strx = str_tbl->len;
260: nl->n_type = N_EXT | N_TEXT;
261: nl->n_value = pc;
262: nl++;
263: strcpy(str_ptr, END_SYMBOL);
264: str_tbl->len += strlen(END_SYMBOL)+1;
265:
266: /* write out the symbol table. */
267: if (write(1, nlbase, exec.a_syms) == -1)
268: die("write(nl)");
269:
270: /* write out the string table */
271: if (write(1, str_tbl, str_tbl->len) == -1)
272: die("write(str_tbl)");
273:
274: /* update the header to reflect the true text size */
275: if (lseek(1, 0, 0L) == -1)
276: die("lseek");
277: if (write(1, &exec, sizeof exec) == -1)
278: die("write(exec)");
279:
280: return 0;
281: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.