remove uses of strncmp() in outelf_archive()
[ld.git] / ld.c
blob0ff1b2c0676b56d6851b00a8503ef99de9dd6a94
1 /*
2 * ld - a small static linker
4 * Copyright (C) 2010-2011 Ali Gholami Rudi
6 * This program is released under GNU GPL version 2.
7 */
8 #include <ctype.h>
9 #include <elf.h>
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <sys/stat.h>
14 #include <string.h>
15 #include <unistd.h>
17 #define I_CS 0
18 #define I_DS 1
19 #define I_BSS 2
21 static unsigned long sec_vaddr[3] = {0x800000}; /* virtual address of sections */
22 static unsigned long sec_laddr[3] = {0x800000}; /* load address of sections */
23 static int sec_set[3] = {1}; /* set address for section */
24 static int secalign = 16; /* section alignment */
26 #define MAXSECS (1 << 10)
27 #define MAXOBJS (1 << 7)
28 #define MAXSYMS (1 << 12)
29 #define PAGE_SIZE (1 << 12)
30 #define PAGE_MASK (PAGE_SIZE - 1)
31 #define MAXFILES (1 << 10)
32 #define MAXPHDRS 4
34 #define MAX(a, b) ((a) > (b) ? (a) : (b))
35 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
37 struct obj {
38 char *mem;
39 Elf32_Ehdr *ehdr;
40 Elf32_Shdr *shdr;
41 Elf32_Sym *syms;
42 int nsyms;
43 char *symstr;
44 char *shstr;
47 struct secmap {
48 Elf32_Shdr *o_shdr;
49 struct obj *obj;
50 unsigned long vaddr;
51 unsigned long faddr;
54 struct bss_sym {
55 Elf32_Sym *sym;
56 int off;
59 struct outelf {
60 Elf32_Ehdr ehdr;
61 Elf32_Phdr phdr[MAXSECS];
62 int nph;
63 struct secmap secs[MAXSECS];
64 int nsecs;
65 struct obj objs[MAXOBJS];
66 int nobjs;
68 /* code section */
69 unsigned long code_addr;
71 /* bss section */
72 struct bss_sym bss_syms[MAXSYMS];
73 int nbss_syms;
74 unsigned long bss_vaddr;
75 int bss_len;
77 /* symtab section */
78 Elf32_Shdr shdr[MAXSECS];
79 int nsh;
80 char symstr[MAXSYMS];
81 Elf32_Sym syms[MAXSYMS];
82 int nsyms;
83 int nsymstr;
84 unsigned long shdr_faddr;
85 unsigned long syms_faddr;
86 unsigned long symstr_faddr;
89 static int nosyms = 0;
91 static Elf32_Sym *obj_find(struct obj *obj, char *name)
93 int i;
94 for (i = 0; i < obj->nsyms; i++) {
95 Elf32_Sym *sym = &obj->syms[i];
96 if (ELF32_ST_BIND(sym->st_info) == STB_LOCAL ||
97 sym->st_shndx == SHN_UNDEF)
98 continue;
99 if (!strcmp(name, obj->symstr + sym->st_name))
100 return sym;
102 return NULL;
105 static void obj_init(struct obj *obj, char *mem)
107 int i;
108 obj->mem = mem;
109 obj->ehdr = (void *) mem;
110 obj->shdr = (void *) (mem + obj->ehdr->e_shoff);
111 obj->shstr = mem + obj->shdr[obj->ehdr->e_shstrndx].sh_offset;
112 for (i = 0; i < obj->ehdr->e_shnum; i++) {
113 if (obj->shdr[i].sh_type != SHT_SYMTAB)
114 continue;
115 obj->symstr = mem + obj->shdr[obj->shdr[i].sh_link].sh_offset;
116 obj->syms = (void *) (mem + obj->shdr[i].sh_offset);
117 obj->nsyms = obj->shdr[i].sh_size / sizeof(*obj->syms);
121 static void outelf_init(struct outelf *oe)
123 memset(oe, 0, sizeof(*oe));
124 oe->ehdr.e_ident[0] = 0x7f;
125 oe->ehdr.e_ident[1] = 'E';
126 oe->ehdr.e_ident[2] = 'L';
127 oe->ehdr.e_ident[3] = 'F';
128 oe->ehdr.e_ident[4] = ELFCLASS32;
129 oe->ehdr.e_ident[5] = ELFDATA2LSB;
130 oe->ehdr.e_ident[6] = EV_CURRENT;
131 oe->ehdr.e_type = ET_EXEC;
132 oe->ehdr.e_machine = EM_386;
133 oe->ehdr.e_version = EV_CURRENT;
134 oe->ehdr.e_shstrndx = SHN_UNDEF;
135 oe->ehdr.e_ehsize = sizeof(oe->ehdr);
136 oe->ehdr.e_phentsize = sizeof(oe->phdr[0]);
137 oe->ehdr.e_shentsize = sizeof(Elf32_Shdr);
140 static struct secmap *outelf_mapping(struct outelf *oe, Elf32_Shdr *shdr)
142 int i;
143 for (i = 0; i < oe->nsecs; i++)
144 if (oe->secs[i].o_shdr == shdr)
145 return &oe->secs[i];
146 return NULL;
149 static int outelf_find(struct outelf *oe, char *name,
150 struct obj **sym_obj, Elf32_Sym **sym_sym)
152 int i;
153 for (i = 0; i < oe->nobjs; i++) {
154 struct obj *obj = &oe->objs[i];
155 Elf32_Sym *sym;
156 if ((sym = obj_find(obj, name))) {
157 *sym_obj = obj;
158 *sym_sym = sym;
159 return 0;
162 return 1;
165 static unsigned long bss_addr(struct outelf *oe, Elf32_Sym *sym)
167 int i;
168 for (i = 0; i < oe->nbss_syms; i++)
169 if (oe->bss_syms[i].sym == sym)
170 return oe->bss_vaddr + oe->bss_syms[i].off;
171 return 0;
174 static void die(char *msg)
176 fprintf(stderr, "%s\n", msg);
177 exit(1);
180 static void die_undef(char *name)
182 fprintf(stderr, "%s undefined\n", name);
183 exit(1);
186 static unsigned long symval(struct outelf *oe, struct obj *obj, Elf32_Sym *sym)
188 struct secmap *sec;
189 char *name = obj ? obj->symstr + sym->st_name : NULL;
190 int s_idx, s_off;
191 switch (ELF32_ST_TYPE(sym->st_info)) {
192 case STT_SECTION:
193 if ((sec = outelf_mapping(oe, &obj->shdr[sym->st_shndx])))
194 return sec->vaddr;
195 break;
196 case STT_NOTYPE:
197 case STT_OBJECT:
198 case STT_FUNC:
199 if (name && *name && sym->st_shndx == SHN_UNDEF)
200 if (outelf_find(oe, name, &obj, &sym))
201 die_undef(name);
202 if (sym->st_shndx == SHN_COMMON)
203 return bss_addr(oe, sym);
204 s_idx = sym->st_shndx;
205 s_off = sym->st_value;
206 sec = outelf_mapping(oe, &obj->shdr[s_idx]);
207 if ((sec = outelf_mapping(oe, &obj->shdr[s_idx])))
208 return sec->vaddr + s_off;
210 return 0;
213 static unsigned long outelf_addr(struct outelf *oe, char *name)
215 struct obj *obj;
216 Elf32_Sym *sym;
217 if (outelf_find(oe, name, &obj, &sym))
218 die_undef(name);
219 return symval(oe, obj, sym);
222 static void outelf_reloc_sec(struct outelf *oe, int o_idx, int s_idx)
224 struct obj *obj = &oe->objs[o_idx];
225 Elf32_Shdr *rel_shdr = &obj->shdr[s_idx];
226 Elf32_Rel *rels = (void *) obj->mem + obj->shdr[s_idx].sh_offset;
227 Elf32_Shdr *other_shdr = &obj->shdr[rel_shdr->sh_info];
228 void *other = (void *) obj->mem + other_shdr->sh_offset;
229 int nrels = rel_shdr->sh_size / sizeof(*rels);
230 unsigned long addr;
231 int i;
232 for (i = 0; i < nrels; i++) {
233 Elf32_Rela *rel = (void *) &rels[i];
234 int sym_idx = ELF32_R_SYM(rel->r_info);
235 Elf32_Sym *sym = &obj->syms[sym_idx];
236 unsigned long val = symval(oe, obj, sym);
237 unsigned long *dst = other + rel->r_offset;
238 switch (ELF32_R_TYPE(rel->r_info)) {
239 case R_386_NONE:
240 break;
241 case R_386_16:
242 *(unsigned short *) dst += val;
243 break;
244 case R_386_32:
245 *dst += val;
246 break;
247 case R_386_PC32:
248 case R_386_PLT32:
249 addr = outelf_mapping(oe, other_shdr)->vaddr +
250 rel->r_offset;
251 *dst += val - addr;
252 break;
253 default:
254 die("unknown relocation type");
259 static void outelf_reloc(struct outelf *oe)
261 int i, j;
262 for (i = 0; i < oe->nobjs; i++) {
263 struct obj *obj = &oe->objs[i];
264 for (j = 0; j < obj->ehdr->e_shnum; j++)
265 if (obj->shdr[j].sh_type == SHT_REL)
266 outelf_reloc_sec(oe, i, j);
270 static void alloc_bss(struct outelf *oe, Elf32_Sym *sym)
272 int n = oe->nbss_syms++;
273 int off = ALIGN(oe->bss_len, MAX(sym->st_value, 4));
274 oe->bss_syms[n].sym = sym;
275 oe->bss_syms[n].off = off;
276 oe->bss_len = off + sym->st_size;
279 static void outelf_bss(struct outelf *oe)
281 int i, j;
282 for (i = 0; i < oe->nobjs; i++) {
283 struct obj *obj = &oe->objs[i];
284 for (j = 0; j < obj->nsyms; j++)
285 if (obj->syms[j].st_shndx == SHN_COMMON)
286 alloc_bss(oe, &obj->syms[j]);
290 #define SEC_CODE(s) ((s)->sh_flags & SHF_EXECINSTR)
291 #define SEC_BSS(s) ((s)->sh_type == SHT_NOBITS)
292 #define SEC_DATA(s) (!SEC_CODE(s) && !SEC_BSS(s))
294 static char *putstr(char *d, char *s)
296 while (*s)
297 *d++ = *s++;
298 *d++ = '\0';
299 return d;
302 static void build_symtab(struct outelf *oe)
304 int i, j;
305 char *symstr = oe->symstr;
306 Elf32_Sym *syms = oe->syms;
307 Elf32_Shdr *sym_shdr = &oe->shdr[1];
308 Elf32_Shdr *str_shdr = &oe->shdr[2];
309 int n = 1;
310 char *s = putstr(symstr, "");
311 int faddr = oe->shdr_faddr;
312 oe->nsh = 3;
313 for (i = 0; i < oe->nobjs; i++) {
314 struct obj *obj = &oe->objs[i];
315 for (j = 0; j < obj->nsyms; j++) {
316 Elf32_Sym *sym = &obj->syms[j];
317 int type = ELF32_ST_TYPE(sym->st_info);
318 int bind = ELF32_ST_BIND(sym->st_info);
319 char *name = obj->symstr + sym->st_name;
320 if (!*name || bind == STB_LOCAL ||
321 sym->st_shndx == SHN_UNDEF)
322 continue;
323 syms[n].st_name = s - symstr;
324 s = putstr(s, name);
325 syms[n].st_info = ELF32_ST_INFO(bind, type);
326 syms[n].st_value = symval(oe, obj, sym);
327 syms[n].st_size = sym->st_size;
328 syms[n].st_shndx = SHN_ABS;
329 n++;
332 oe->nsymstr = s - symstr;
333 oe->nsyms = n;
335 oe->shdr_faddr = faddr;
336 faddr += oe->nsh * sizeof(oe->shdr[0]);
337 oe->syms_faddr = faddr;
338 faddr += oe->nsyms * sizeof(oe->syms[0]);
339 oe->symstr_faddr = faddr;
340 faddr += oe->nsymstr;
342 oe->ehdr.e_shstrndx = str_shdr - oe->shdr;
343 oe->ehdr.e_shoff = oe->shdr_faddr;
344 oe->ehdr.e_shnum = oe->nsh;
346 str_shdr->sh_name = 0;
347 str_shdr->sh_type = SHT_STRTAB;
348 str_shdr->sh_offset = oe->symstr_faddr;
349 str_shdr->sh_size = oe->nsymstr;
351 sym_shdr->sh_name = 0;
352 sym_shdr->sh_type = SHT_SYMTAB;
353 sym_shdr->sh_entsize = sizeof(oe->syms[0]);
354 sym_shdr->sh_offset = oe->syms_faddr;
355 sym_shdr->sh_size = oe->nsyms * sizeof(oe->syms[0]);
356 sym_shdr->sh_link = str_shdr - oe->shdr;
357 sym_shdr->sh_info = 0;
360 static void outelf_write(struct outelf *oe, int fd)
362 int i;
363 oe->ehdr.e_entry = outelf_addr(oe, "_start") -
364 sec_vaddr[I_CS] + sec_laddr[I_CS];
365 if (!nosyms)
366 build_symtab(oe);
367 oe->ehdr.e_phnum = oe->nph;
368 oe->ehdr.e_phoff = sizeof(oe->ehdr);
369 lseek(fd, 0, SEEK_SET);
370 write(fd, &oe->ehdr, sizeof(oe->ehdr));
371 write(fd, &oe->phdr, oe->nph * sizeof(oe->phdr[0]));
372 for (i = 0; i < oe->nsecs; i++) {
373 struct secmap *sec = &oe->secs[i];
374 char *buf = sec->obj->mem + sec->o_shdr->sh_offset;
375 int len = sec->o_shdr->sh_size;
376 if (SEC_BSS(sec->o_shdr))
377 continue;
378 lseek(fd, sec->faddr, SEEK_SET);
379 write(fd, buf, len);
381 if (!nosyms) {
382 lseek(fd, oe->shdr_faddr, SEEK_SET);
383 write(fd, &oe->shdr, oe->nsh * sizeof(oe->shdr[0]));
384 lseek(fd, oe->syms_faddr, SEEK_SET);
385 write(fd, &oe->syms, oe->nsyms * sizeof(oe->syms[0]));
386 lseek(fd, oe->symstr_faddr, SEEK_SET);
387 write(fd, &oe->symstr, oe->nsymstr);
391 static void outelf_add(struct outelf *oe, char *mem)
393 Elf32_Ehdr *ehdr = (void *) mem;
394 Elf32_Shdr *shdr = (void *) (mem + ehdr->e_shoff);
395 struct obj *obj;
396 int i;
397 if (ehdr->e_type != ET_REL)
398 return;
399 if (oe->nobjs >= MAXOBJS)
400 die("ld: MAXOBJS reached!");
401 obj = &oe->objs[oe->nobjs++];
402 obj_init(obj, mem);
403 for (i = 0; i < ehdr->e_shnum; i++) {
404 struct secmap *sec;
405 if (!(shdr[i].sh_flags & 0x7))
406 continue;
407 if (oe->nsecs >= MAXSECS)
408 die("ld: MAXSECS reached");
409 sec = &oe->secs[oe->nsecs++];
410 sec->o_shdr = &shdr[i];
411 sec->obj = obj;
415 static int link_cs(struct outelf *oe, Elf32_Phdr *phdr, unsigned long faddr,
416 unsigned long vaddr, unsigned long laddr, int len)
418 int i;
419 for (i = 0; i < oe->nsecs; i++) {
420 struct secmap *sec = &oe->secs[i];
421 int alignment = MAX(sec->o_shdr->sh_addralign, 4);
422 if (!SEC_CODE(sec->o_shdr))
423 continue;
424 len = ALIGN(vaddr + len, alignment) - vaddr;
425 sec->vaddr = vaddr + len;
426 sec->faddr = faddr + len;
427 len += sec->o_shdr->sh_size;
429 phdr->p_type = PT_LOAD;
430 phdr->p_flags = PF_R | PF_W | PF_X;
431 phdr->p_vaddr = vaddr;
432 phdr->p_paddr = laddr;
433 phdr->p_offset = faddr;
434 phdr->p_filesz = len;
435 phdr->p_memsz = len;
436 phdr->p_align = PAGE_SIZE;
437 return len;
440 static int link_ds(struct outelf *oe, Elf32_Phdr *phdr, unsigned long faddr,
441 unsigned long vaddr, unsigned long laddr)
443 int len = 0;
444 int i;
445 for (i = 0; i < oe->nsecs; i++) {
446 struct secmap *sec = &oe->secs[i];
447 if (!SEC_DATA(sec->o_shdr))
448 continue;
449 sec->vaddr = vaddr + len;
450 sec->faddr = faddr + len;
451 len += sec->o_shdr->sh_size;
453 len = ALIGN(len, 4);
454 phdr->p_type = PT_LOAD;
455 phdr->p_flags = PF_R | PF_W | PF_X;
456 phdr->p_align = PAGE_SIZE;
457 phdr->p_vaddr = vaddr;
458 phdr->p_paddr = laddr;
459 phdr->p_filesz = len;
460 phdr->p_memsz = len;
461 phdr->p_offset = faddr;
462 return len;
465 static int link_bss(struct outelf *oe, Elf32_Phdr *phdr,
466 unsigned long faddr, unsigned long vaddr, int len)
468 int i;
469 for (i = 0; i < oe->nsecs; i++) {
470 struct secmap *sec = &oe->secs[i];
471 int alignment = MAX(sec->o_shdr->sh_addralign, 4);
472 if (!SEC_BSS(sec->o_shdr))
473 continue;
474 len = ALIGN(vaddr + len, alignment) - vaddr;
475 sec->vaddr = vaddr + len;
476 sec->faddr = faddr;
477 len += sec->o_shdr->sh_size;
479 phdr->p_type = PT_LOAD;
480 phdr->p_flags = PF_R | PF_W;
481 phdr->p_vaddr = vaddr;
482 phdr->p_paddr = vaddr;
483 phdr->p_offset = faddr;
484 phdr->p_filesz = 0;
485 phdr->p_memsz = len;
486 phdr->p_align = PAGE_SIZE;
487 return len;
490 static void outelf_link(struct outelf *oe)
492 unsigned long faddr, vaddr, laddr;
493 int len;
494 len = ALIGN(sizeof(oe->ehdr) + MAXPHDRS * sizeof(oe->phdr[0]), secalign);
495 faddr = len & ~PAGE_MASK;
496 vaddr = sec_vaddr[I_CS];
497 laddr = sec_laddr[I_CS];
498 len = link_cs(oe, &oe->phdr[0], faddr, vaddr, laddr, len & PAGE_MASK);
500 len = ALIGN(faddr + len, secalign) - faddr;
501 faddr += len;
502 vaddr = sec_set[I_DS] ? sec_vaddr[I_DS] | (faddr & PAGE_MASK) : vaddr + len;
503 laddr = sec_set[I_DS] ? sec_laddr[I_DS] | (faddr & PAGE_MASK) : laddr + len;
504 len = link_ds(oe, &oe->phdr[1], faddr, vaddr, laddr);
506 len = ALIGN(faddr + len, secalign) - faddr;
507 faddr += len;
508 vaddr = sec_set[I_BSS] ? sec_vaddr[I_BSS] | (faddr & PAGE_MASK) : vaddr + len;
509 outelf_bss(oe);
510 oe->bss_vaddr = vaddr;
511 len = link_bss(oe, &oe->phdr[2], faddr, vaddr, oe->bss_len);
513 oe->nph = 3;
514 outelf_reloc(oe);
515 oe->shdr_faddr = faddr;
518 struct arhdr {
519 char ar_name[16];
520 char ar_date[12];
521 char ar_uid[6];
522 char ar_gid[6];
523 char ar_mode[8];
524 char ar_size[10];
525 char ar_fmag[2];
528 static int get_be32(unsigned char *s)
530 return s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24);
533 static int sym_undef(struct outelf *oe, char *name)
535 int i, j;
536 int undef = 0;
537 for (i = 0; i < oe->nobjs; i++) {
538 struct obj *obj = &oe->objs[i];
539 for (j = 0; j < obj->nsyms; j++) {
540 Elf32_Sym *sym = &obj->syms[j];
541 if (ELF32_ST_BIND(sym->st_info) == STB_LOCAL)
542 continue;
543 if (strcmp(name, obj->symstr + sym->st_name))
544 continue;
545 if (sym->st_shndx != SHN_UNDEF)
546 return 0;
547 undef = 1;
550 return undef;
553 static int outelf_ar_link(struct outelf *oe, char *ar, int base)
555 char *ar_index;
556 char *ar_name;
557 int nsyms = get_be32((void *) ar);
558 int added = 0;
559 int i;
560 ar_index = ar + 4;
561 ar_name = ar_index + nsyms * 4;
562 for (i = 0; i < nsyms; i++) {
563 int off = get_be32((void *) ar_index + i * 4) +
564 sizeof(struct arhdr);
565 if (sym_undef(oe, ar_name)) {
566 outelf_add(oe, ar - base + off);
567 added++;
569 ar_name = strchr(ar_name, '\0') + 1;
571 return added;
574 static void outelf_archive(struct outelf *oe, char *ar)
576 char *beg = ar;
578 /* skip magic */
579 ar += 8;
580 for(;;) {
581 struct arhdr *hdr = (void *) ar;
582 char *name = hdr->ar_name;
583 int size;
584 ar += sizeof(*hdr);
585 hdr->ar_size[sizeof(hdr->ar_size) - 1] = '\0';
586 size = atoi(hdr->ar_size);
587 size = (size + 1) & ~1;
588 if (name[0] == '/' && name[1] == ' ') {
589 while (outelf_ar_link(oe, ar, ar - beg))
591 return;
593 if (name[0] == '/' && name[1] == '/' && name[2] == ' ')
594 outelf_add(oe, ar);
595 ar += size;
599 static long filesize(int fd)
601 struct stat stat;
602 fstat(fd, &stat);
603 return stat.st_size;
606 static char *fileread(char *path)
608 int fd = open(path, O_RDONLY);
609 int size = filesize(fd);
610 char *buf = malloc(size);
611 read(fd, buf, size);
612 close(fd);
613 return buf;
616 static int is_ar(char *path)
618 int len = strlen(path);
619 return len > 2 && path[len - 2] == '.' && path[len - 1] == 'a';
622 #define LIBDIRS (1 << 5)
623 #define PATHLEN (1 << 8)
625 static char *libdirs[LIBDIRS] = {"/lib"};
626 static int nlibdirs = 1;
628 static int lib_find(char *path, char *lib)
630 struct stat st;
631 int i;
632 for (i = 0; i < nlibdirs; i++) {
633 sprintf(path, "%s/lib%s.a", libdirs[i], lib);
634 if (!stat(path, &st))
635 return 0;
637 return 1;
640 unsigned long hexnum(char *s)
642 unsigned long n = 0;
643 if (s[0] == '0' && s[1] == 'x')
644 s += 2;
645 for (; isdigit(*s) || isalpha(*s); s++) {
646 n <<= 4;
647 n |= isdigit(*s) ? *s - '0' : tolower(*s) - 'a' + 10;
649 return n;
652 static void set_addr(int sec, char *arg)
654 int idx = I_CS;
655 char *sep = strchr(arg, ':');
656 if (sec == 'd')
657 idx = I_DS;
658 if (sec == 'b')
659 idx = I_BSS;
660 sec_vaddr[idx] = hexnum(arg);
661 sec_laddr[idx] = sep ? hexnum(sep + 1) : sec_vaddr[idx];
662 sec_set[idx] = 1;
665 static char *obj_add(struct outelf *oe, char *path)
667 char *buf = fileread(path);
668 if (!buf)
669 die("cannot open object");
670 if (is_ar(path))
671 outelf_archive(oe, buf);
672 else
673 outelf_add(oe, buf);
674 return buf;
677 int main(int argc, char **argv)
679 char out[PATHLEN] = "a.out";
680 struct outelf oe;
681 char *mem[MAXFILES];
682 int nmem = 0;
683 int fd;
684 int i = 0;
685 if (argc < 2)
686 die("no object given");
687 outelf_init(&oe);
689 while (++i < argc) {
690 if (argv[i][0] != '-') {
691 mem[nmem++] = obj_add(&oe, argv[i]);
692 continue;
694 if (argv[i][1] == 'l') {
695 char path[PATHLEN];
696 if (lib_find(path, argv[i] + 2))
697 die("cannot find library");
698 mem[nmem++] = obj_add(&oe, path);
699 continue;
701 if (argv[i][1] == 'L') {
702 libdirs[nlibdirs++] = argv[i][2] ? argv[i] + 2 : argv[++i];
703 continue;
705 if (argv[i][1] == 'o') {
706 strcpy(out, argv[i][2] ? argv[i] + 2 : argv[++i]);
707 continue;
709 if (argv[i][1] == 's') {
710 nosyms = 1;
711 continue;
713 if (argv[i][1] == 'g')
714 continue;
715 if (argv[i][1] == 'm') {
716 char sec = argv[i][2];
717 char *arg = argv[i][3] == '=' ? argv[i] + 4 : argv[++i];
718 set_addr(sec, arg);
719 continue;
721 if (argv[i][1] == 'p') {
722 secalign = PAGE_SIZE;
723 continue;
726 outelf_link(&oe);
727 fd = open(out, O_WRONLY | O_TRUNC | O_CREAT, 0700);
728 outelf_write(&oe, fd);
729 close(fd);
730 for (i = 0; i < nmem; i++)
731 free(mem[i]);
732 return 0;