specify entry symbol with -e argument
[ld.git] / ld.c
blobe545c95f42fa4ec7b163d01ee374c1dce130fea3
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 */
25 static char *entry = "_start"; /* entry symbol */
27 #define MAXSECS (1 << 10)
28 #define MAXOBJS (1 << 7)
29 #define MAXSYMS (1 << 12)
30 #define PAGE_SIZE (1 << 12)
31 #define PAGE_MASK (PAGE_SIZE - 1)
32 #define MAXFILES (1 << 10)
33 #define MAXPHDRS 4
35 #define MAX(a, b) ((a) > (b) ? (a) : (b))
36 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
38 struct obj {
39 char *mem;
40 Elf32_Ehdr *ehdr;
41 Elf32_Shdr *shdr;
42 Elf32_Sym *syms;
43 int nsyms;
44 char *symstr;
45 char *shstr;
48 struct secmap {
49 Elf32_Shdr *o_shdr;
50 struct obj *obj;
51 unsigned long vaddr;
52 unsigned long faddr;
55 struct bss_sym {
56 Elf32_Sym *sym;
57 int off;
60 struct outelf {
61 Elf32_Ehdr ehdr;
62 Elf32_Phdr phdr[MAXSECS];
63 int nph;
64 struct secmap secs[MAXSECS];
65 int nsecs;
66 struct obj objs[MAXOBJS];
67 int nobjs;
69 /* code section */
70 unsigned long code_addr;
72 /* bss section */
73 struct bss_sym bss_syms[MAXSYMS];
74 int nbss_syms;
75 unsigned long bss_vaddr;
76 int bss_len;
78 /* symtab section */
79 Elf32_Shdr shdr[MAXSECS];
80 int nsh;
81 char symstr[MAXSYMS];
82 Elf32_Sym syms[MAXSYMS];
83 int nsyms;
84 int nsymstr;
85 unsigned long shdr_faddr;
86 unsigned long syms_faddr;
87 unsigned long symstr_faddr;
90 static int nosyms = 0;
92 static Elf32_Sym *obj_find(struct obj *obj, char *name)
94 int i;
95 for (i = 0; i < obj->nsyms; i++) {
96 Elf32_Sym *sym = &obj->syms[i];
97 if (ELF32_ST_BIND(sym->st_info) == STB_LOCAL ||
98 sym->st_shndx == SHN_UNDEF)
99 continue;
100 if (!strcmp(name, obj->symstr + sym->st_name))
101 return sym;
103 return NULL;
106 static void obj_init(struct obj *obj, char *mem)
108 int i;
109 obj->mem = mem;
110 obj->ehdr = (void *) mem;
111 obj->shdr = (void *) (mem + obj->ehdr->e_shoff);
112 obj->shstr = mem + obj->shdr[obj->ehdr->e_shstrndx].sh_offset;
113 for (i = 0; i < obj->ehdr->e_shnum; i++) {
114 if (obj->shdr[i].sh_type != SHT_SYMTAB)
115 continue;
116 obj->symstr = mem + obj->shdr[obj->shdr[i].sh_link].sh_offset;
117 obj->syms = (void *) (mem + obj->shdr[i].sh_offset);
118 obj->nsyms = obj->shdr[i].sh_size / sizeof(*obj->syms);
122 static void outelf_init(struct outelf *oe)
124 memset(oe, 0, sizeof(*oe));
125 oe->ehdr.e_ident[0] = 0x7f;
126 oe->ehdr.e_ident[1] = 'E';
127 oe->ehdr.e_ident[2] = 'L';
128 oe->ehdr.e_ident[3] = 'F';
129 oe->ehdr.e_ident[4] = ELFCLASS32;
130 oe->ehdr.e_ident[5] = ELFDATA2LSB;
131 oe->ehdr.e_ident[6] = EV_CURRENT;
132 oe->ehdr.e_type = ET_EXEC;
133 oe->ehdr.e_machine = EM_386;
134 oe->ehdr.e_version = EV_CURRENT;
135 oe->ehdr.e_shstrndx = SHN_UNDEF;
136 oe->ehdr.e_ehsize = sizeof(oe->ehdr);
137 oe->ehdr.e_phentsize = sizeof(oe->phdr[0]);
138 oe->ehdr.e_shentsize = sizeof(Elf32_Shdr);
141 static struct secmap *outelf_mapping(struct outelf *oe, Elf32_Shdr *shdr)
143 int i;
144 for (i = 0; i < oe->nsecs; i++)
145 if (oe->secs[i].o_shdr == shdr)
146 return &oe->secs[i];
147 return NULL;
150 static int outelf_find(struct outelf *oe, char *name,
151 struct obj **sym_obj, Elf32_Sym **sym_sym)
153 int i;
154 for (i = 0; i < oe->nobjs; i++) {
155 struct obj *obj = &oe->objs[i];
156 Elf32_Sym *sym;
157 if ((sym = obj_find(obj, name))) {
158 *sym_obj = obj;
159 *sym_sym = sym;
160 return 0;
163 return 1;
166 static unsigned long bss_addr(struct outelf *oe, Elf32_Sym *sym)
168 int i;
169 for (i = 0; i < oe->nbss_syms; i++)
170 if (oe->bss_syms[i].sym == sym)
171 return oe->bss_vaddr + oe->bss_syms[i].off;
172 return 0;
175 static void die(char *msg)
177 fprintf(stderr, "%s\n", msg);
178 exit(1);
181 static void die_undef(char *name)
183 fprintf(stderr, "%s undefined\n", name);
184 exit(1);
187 static unsigned long symval(struct outelf *oe, struct obj *obj, Elf32_Sym *sym)
189 struct secmap *sec;
190 char *name = obj ? obj->symstr + sym->st_name : NULL;
191 int s_idx, s_off;
192 switch (ELF32_ST_TYPE(sym->st_info)) {
193 case STT_SECTION:
194 if ((sec = outelf_mapping(oe, &obj->shdr[sym->st_shndx])))
195 return sec->vaddr;
196 break;
197 case STT_NOTYPE:
198 case STT_OBJECT:
199 case STT_FUNC:
200 if (name && *name && sym->st_shndx == SHN_UNDEF)
201 if (outelf_find(oe, name, &obj, &sym))
202 die_undef(name);
203 if (sym->st_shndx == SHN_COMMON)
204 return bss_addr(oe, sym);
205 s_idx = sym->st_shndx;
206 s_off = sym->st_value;
207 sec = outelf_mapping(oe, &obj->shdr[s_idx]);
208 if ((sec = outelf_mapping(oe, &obj->shdr[s_idx])))
209 return sec->vaddr + s_off;
211 return 0;
214 static unsigned long outelf_addr(struct outelf *oe, char *name)
216 struct obj *obj;
217 Elf32_Sym *sym;
218 if (outelf_find(oe, name, &obj, &sym))
219 die_undef(name);
220 return symval(oe, obj, sym);
223 static void outelf_reloc_sec(struct outelf *oe, int o_idx, int s_idx)
225 struct obj *obj = &oe->objs[o_idx];
226 Elf32_Shdr *rel_shdr = &obj->shdr[s_idx];
227 Elf32_Rel *rels = (void *) obj->mem + obj->shdr[s_idx].sh_offset;
228 Elf32_Shdr *other_shdr = &obj->shdr[rel_shdr->sh_info];
229 void *other = (void *) obj->mem + other_shdr->sh_offset;
230 int nrels = rel_shdr->sh_size / sizeof(*rels);
231 unsigned long addr;
232 int i;
233 for (i = 0; i < nrels; i++) {
234 Elf32_Rela *rel = (void *) &rels[i];
235 int sym_idx = ELF32_R_SYM(rel->r_info);
236 Elf32_Sym *sym = &obj->syms[sym_idx];
237 unsigned long val = symval(oe, obj, sym);
238 unsigned long *dst = other + rel->r_offset;
239 switch (ELF32_R_TYPE(rel->r_info)) {
240 case R_386_NONE:
241 break;
242 case R_386_16:
243 *(unsigned short *) dst += val;
244 break;
245 case R_386_32:
246 *dst += val;
247 break;
248 case R_386_PC32:
249 case R_386_PLT32:
250 addr = outelf_mapping(oe, other_shdr)->vaddr +
251 rel->r_offset;
252 *dst += val - addr;
253 break;
254 default:
255 die("unknown relocation type");
260 static void outelf_reloc(struct outelf *oe)
262 int i, j;
263 for (i = 0; i < oe->nobjs; i++) {
264 struct obj *obj = &oe->objs[i];
265 for (j = 0; j < obj->ehdr->e_shnum; j++)
266 if (obj->shdr[j].sh_type == SHT_REL)
267 outelf_reloc_sec(oe, i, j);
271 static void alloc_bss(struct outelf *oe, Elf32_Sym *sym)
273 int n = oe->nbss_syms++;
274 int off = ALIGN(oe->bss_len, MAX(sym->st_value, 4));
275 oe->bss_syms[n].sym = sym;
276 oe->bss_syms[n].off = off;
277 oe->bss_len = off + sym->st_size;
280 static void outelf_bss(struct outelf *oe)
282 int i, j;
283 for (i = 0; i < oe->nobjs; i++) {
284 struct obj *obj = &oe->objs[i];
285 for (j = 0; j < obj->nsyms; j++)
286 if (obj->syms[j].st_shndx == SHN_COMMON)
287 alloc_bss(oe, &obj->syms[j]);
291 #define SEC_CODE(s) ((s)->sh_flags & SHF_EXECINSTR)
292 #define SEC_BSS(s) ((s)->sh_type == SHT_NOBITS)
293 #define SEC_DATA(s) (!SEC_CODE(s) && !SEC_BSS(s))
295 static char *putstr(char *d, char *s)
297 while (*s)
298 *d++ = *s++;
299 *d++ = '\0';
300 return d;
303 static void build_symtab(struct outelf *oe)
305 int i, j;
306 char *symstr = oe->symstr;
307 Elf32_Sym *syms = oe->syms;
308 Elf32_Shdr *sym_shdr = &oe->shdr[1];
309 Elf32_Shdr *str_shdr = &oe->shdr[2];
310 int n = 1;
311 char *s = putstr(symstr, "");
312 int faddr = oe->shdr_faddr;
313 oe->nsh = 3;
314 for (i = 0; i < oe->nobjs; i++) {
315 struct obj *obj = &oe->objs[i];
316 for (j = 0; j < obj->nsyms; j++) {
317 Elf32_Sym *sym = &obj->syms[j];
318 int type = ELF32_ST_TYPE(sym->st_info);
319 int bind = ELF32_ST_BIND(sym->st_info);
320 char *name = obj->symstr + sym->st_name;
321 if (!*name || bind == STB_LOCAL ||
322 sym->st_shndx == SHN_UNDEF)
323 continue;
324 syms[n].st_name = s - symstr;
325 s = putstr(s, name);
326 syms[n].st_info = ELF32_ST_INFO(bind, type);
327 syms[n].st_value = symval(oe, obj, sym);
328 syms[n].st_size = sym->st_size;
329 syms[n].st_shndx = SHN_ABS;
330 n++;
333 oe->nsymstr = s - symstr;
334 oe->nsyms = n;
336 oe->shdr_faddr = faddr;
337 faddr += oe->nsh * sizeof(oe->shdr[0]);
338 oe->syms_faddr = faddr;
339 faddr += oe->nsyms * sizeof(oe->syms[0]);
340 oe->symstr_faddr = faddr;
341 faddr += oe->nsymstr;
343 oe->ehdr.e_shstrndx = str_shdr - oe->shdr;
344 oe->ehdr.e_shoff = oe->shdr_faddr;
345 oe->ehdr.e_shnum = oe->nsh;
347 str_shdr->sh_name = 0;
348 str_shdr->sh_type = SHT_STRTAB;
349 str_shdr->sh_offset = oe->symstr_faddr;
350 str_shdr->sh_size = oe->nsymstr;
352 sym_shdr->sh_name = 0;
353 sym_shdr->sh_type = SHT_SYMTAB;
354 sym_shdr->sh_entsize = sizeof(oe->syms[0]);
355 sym_shdr->sh_offset = oe->syms_faddr;
356 sym_shdr->sh_size = oe->nsyms * sizeof(oe->syms[0]);
357 sym_shdr->sh_link = str_shdr - oe->shdr;
358 sym_shdr->sh_info = 0;
361 static void outelf_write(struct outelf *oe, int fd)
363 int i;
364 oe->ehdr.e_entry = outelf_addr(oe, entry) -
365 sec_vaddr[I_CS] + sec_laddr[I_CS];
366 if (!nosyms)
367 build_symtab(oe);
368 oe->ehdr.e_phnum = oe->nph;
369 oe->ehdr.e_phoff = sizeof(oe->ehdr);
370 lseek(fd, 0, SEEK_SET);
371 write(fd, &oe->ehdr, sizeof(oe->ehdr));
372 write(fd, &oe->phdr, oe->nph * sizeof(oe->phdr[0]));
373 for (i = 0; i < oe->nsecs; i++) {
374 struct secmap *sec = &oe->secs[i];
375 char *buf = sec->obj->mem + sec->o_shdr->sh_offset;
376 int len = sec->o_shdr->sh_size;
377 if (SEC_BSS(sec->o_shdr))
378 continue;
379 lseek(fd, sec->faddr, SEEK_SET);
380 write(fd, buf, len);
382 if (!nosyms) {
383 lseek(fd, oe->shdr_faddr, SEEK_SET);
384 write(fd, &oe->shdr, oe->nsh * sizeof(oe->shdr[0]));
385 lseek(fd, oe->syms_faddr, SEEK_SET);
386 write(fd, &oe->syms, oe->nsyms * sizeof(oe->syms[0]));
387 lseek(fd, oe->symstr_faddr, SEEK_SET);
388 write(fd, &oe->symstr, oe->nsymstr);
392 static void outelf_add(struct outelf *oe, char *mem)
394 Elf32_Ehdr *ehdr = (void *) mem;
395 Elf32_Shdr *shdr = (void *) (mem + ehdr->e_shoff);
396 struct obj *obj;
397 int i;
398 if (ehdr->e_type != ET_REL)
399 return;
400 if (oe->nobjs >= MAXOBJS)
401 die("ld: MAXOBJS reached!");
402 obj = &oe->objs[oe->nobjs++];
403 obj_init(obj, mem);
404 for (i = 0; i < ehdr->e_shnum; i++) {
405 struct secmap *sec;
406 if (!(shdr[i].sh_flags & 0x7))
407 continue;
408 if (oe->nsecs >= MAXSECS)
409 die("ld: MAXSECS reached");
410 sec = &oe->secs[oe->nsecs++];
411 sec->o_shdr = &shdr[i];
412 sec->obj = obj;
416 static int link_cs(struct outelf *oe, Elf32_Phdr *phdr, unsigned long faddr,
417 unsigned long vaddr, unsigned long laddr, int len)
419 int i;
420 for (i = 0; i < oe->nsecs; i++) {
421 struct secmap *sec = &oe->secs[i];
422 int alignment = MAX(sec->o_shdr->sh_addralign, 4);
423 if (!SEC_CODE(sec->o_shdr))
424 continue;
425 len = ALIGN(vaddr + len, alignment) - vaddr;
426 sec->vaddr = vaddr + len;
427 sec->faddr = faddr + len;
428 len += sec->o_shdr->sh_size;
430 phdr->p_type = PT_LOAD;
431 phdr->p_flags = PF_R | PF_W | PF_X;
432 phdr->p_vaddr = vaddr;
433 phdr->p_paddr = laddr;
434 phdr->p_offset = faddr;
435 phdr->p_filesz = len;
436 phdr->p_memsz = len;
437 phdr->p_align = PAGE_SIZE;
438 return len;
441 static int link_ds(struct outelf *oe, Elf32_Phdr *phdr, unsigned long faddr,
442 unsigned long vaddr, unsigned long laddr)
444 int len = 0;
445 int i;
446 for (i = 0; i < oe->nsecs; i++) {
447 struct secmap *sec = &oe->secs[i];
448 if (!SEC_DATA(sec->o_shdr))
449 continue;
450 sec->vaddr = vaddr + len;
451 sec->faddr = faddr + len;
452 len += sec->o_shdr->sh_size;
454 len = ALIGN(len, 4);
455 phdr->p_type = PT_LOAD;
456 phdr->p_flags = PF_R | PF_W | PF_X;
457 phdr->p_align = PAGE_SIZE;
458 phdr->p_vaddr = vaddr;
459 phdr->p_paddr = laddr;
460 phdr->p_filesz = len;
461 phdr->p_memsz = len;
462 phdr->p_offset = faddr;
463 return len;
466 static int link_bss(struct outelf *oe, Elf32_Phdr *phdr,
467 unsigned long faddr, unsigned long vaddr, int len)
469 int i;
470 for (i = 0; i < oe->nsecs; i++) {
471 struct secmap *sec = &oe->secs[i];
472 int alignment = MAX(sec->o_shdr->sh_addralign, 4);
473 if (!SEC_BSS(sec->o_shdr))
474 continue;
475 len = ALIGN(vaddr + len, alignment) - vaddr;
476 sec->vaddr = vaddr + len;
477 sec->faddr = faddr;
478 len += sec->o_shdr->sh_size;
480 phdr->p_type = PT_LOAD;
481 phdr->p_flags = PF_R | PF_W;
482 phdr->p_vaddr = vaddr;
483 phdr->p_paddr = vaddr;
484 phdr->p_offset = faddr;
485 phdr->p_filesz = 0;
486 phdr->p_memsz = len;
487 phdr->p_align = PAGE_SIZE;
488 return len;
491 static void outelf_link(struct outelf *oe)
493 unsigned long faddr, vaddr, laddr;
494 int len;
495 len = ALIGN(sizeof(oe->ehdr) + MAXPHDRS * sizeof(oe->phdr[0]), secalign);
496 faddr = len & ~PAGE_MASK;
497 vaddr = sec_vaddr[I_CS];
498 laddr = sec_laddr[I_CS];
499 len = link_cs(oe, &oe->phdr[0], faddr, vaddr, laddr, len & PAGE_MASK);
501 len = ALIGN(faddr + len, secalign) - faddr;
502 faddr += len;
503 vaddr = sec_set[I_DS] ? sec_vaddr[I_DS] | (faddr & PAGE_MASK) : vaddr + len;
504 laddr = sec_set[I_DS] ? sec_laddr[I_DS] | (faddr & PAGE_MASK) : laddr + len;
505 len = link_ds(oe, &oe->phdr[1], faddr, vaddr, laddr);
507 len = ALIGN(faddr + len, secalign) - faddr;
508 faddr += len;
509 vaddr = sec_set[I_BSS] ? sec_vaddr[I_BSS] | (faddr & PAGE_MASK) : vaddr + len;
510 outelf_bss(oe);
511 oe->bss_vaddr = vaddr;
512 len = link_bss(oe, &oe->phdr[2], faddr, vaddr, oe->bss_len);
514 oe->nph = 3;
515 outelf_reloc(oe);
516 oe->shdr_faddr = faddr;
519 struct arhdr {
520 char ar_name[16];
521 char ar_date[12];
522 char ar_uid[6];
523 char ar_gid[6];
524 char ar_mode[8];
525 char ar_size[10];
526 char ar_fmag[2];
529 static int get_be32(unsigned char *s)
531 return s[3] | (s[2] << 8) | (s[1] << 16) | (s[0] << 24);
534 static int sym_undef(struct outelf *oe, char *name)
536 int i, j;
537 int undef = 0;
538 for (i = 0; i < oe->nobjs; i++) {
539 struct obj *obj = &oe->objs[i];
540 for (j = 0; j < obj->nsyms; j++) {
541 Elf32_Sym *sym = &obj->syms[j];
542 if (ELF32_ST_BIND(sym->st_info) == STB_LOCAL)
543 continue;
544 if (strcmp(name, obj->symstr + sym->st_name))
545 continue;
546 if (sym->st_shndx != SHN_UNDEF)
547 return 0;
548 undef = 1;
551 return undef;
554 static int outelf_ar_link(struct outelf *oe, char *ar, int base)
556 char *ar_index;
557 char *ar_name;
558 int nsyms = get_be32((void *) ar);
559 int added = 0;
560 int i;
561 ar_index = ar + 4;
562 ar_name = ar_index + nsyms * 4;
563 for (i = 0; i < nsyms; i++) {
564 int off = get_be32((void *) ar_index + i * 4) +
565 sizeof(struct arhdr);
566 if (sym_undef(oe, ar_name)) {
567 outelf_add(oe, ar - base + off);
568 added++;
570 ar_name = strchr(ar_name, '\0') + 1;
572 return added;
575 static void outelf_archive(struct outelf *oe, char *ar)
577 char *beg = ar;
579 /* skip magic */
580 ar += 8;
581 for(;;) {
582 struct arhdr *hdr = (void *) ar;
583 char *name = hdr->ar_name;
584 int size;
585 ar += sizeof(*hdr);
586 hdr->ar_size[sizeof(hdr->ar_size) - 1] = '\0';
587 size = atoi(hdr->ar_size);
588 size = (size + 1) & ~1;
589 if (name[0] == '/' && name[1] == ' ') {
590 while (outelf_ar_link(oe, ar, ar - beg))
592 return;
594 if (name[0] == '/' && name[1] == '/' && name[2] == ' ')
595 outelf_add(oe, ar);
596 ar += size;
600 static long filesize(int fd)
602 struct stat stat;
603 fstat(fd, &stat);
604 return stat.st_size;
607 static char *fileread(char *path)
609 int fd = open(path, O_RDONLY);
610 int size = filesize(fd);
611 char *buf = malloc(size);
612 read(fd, buf, size);
613 close(fd);
614 return buf;
617 static int is_ar(char *path)
619 int len = strlen(path);
620 return len > 2 && path[len - 2] == '.' && path[len - 1] == 'a';
623 #define LIBDIRS (1 << 5)
624 #define PATHLEN (1 << 8)
626 static char *libdirs[LIBDIRS] = {"/lib"};
627 static int nlibdirs = 1;
629 static int lib_find(char *path, char *lib)
631 struct stat st;
632 int i;
633 for (i = 0; i < nlibdirs; i++) {
634 sprintf(path, "%s/lib%s.a", libdirs[i], lib);
635 if (!stat(path, &st))
636 return 0;
638 return 1;
641 unsigned long hexnum(char *s)
643 unsigned long n = 0;
644 if (s[0] == '0' && s[1] == 'x')
645 s += 2;
646 for (; isdigit(*s) || isalpha(*s); s++) {
647 n <<= 4;
648 n |= isdigit(*s) ? *s - '0' : tolower(*s) - 'a' + 10;
650 return n;
653 static void set_addr(int sec, char *arg)
655 int idx = I_CS;
656 char *sep = strchr(arg, ':');
657 if (sec == 'd')
658 idx = I_DS;
659 if (sec == 'b')
660 idx = I_BSS;
661 sec_vaddr[idx] = hexnum(arg);
662 sec_laddr[idx] = sep ? hexnum(sep + 1) : sec_vaddr[idx];
663 sec_set[idx] = 1;
666 static char *obj_add(struct outelf *oe, char *path)
668 char *buf = fileread(path);
669 if (!buf)
670 die("cannot open object");
671 if (is_ar(path))
672 outelf_archive(oe, buf);
673 else
674 outelf_add(oe, buf);
675 return buf;
678 int main(int argc, char **argv)
680 char out[PATHLEN] = "a.out";
681 struct outelf oe;
682 char *mem[MAXFILES];
683 int nmem = 0;
684 int fd;
685 int i = 0;
686 if (argc < 2)
687 die("no object given");
688 outelf_init(&oe);
690 while (++i < argc) {
691 if (argv[i][0] != '-') {
692 mem[nmem++] = obj_add(&oe, argv[i]);
693 continue;
695 if (argv[i][1] == 'l') {
696 char path[PATHLEN];
697 if (lib_find(path, argv[i] + 2))
698 die("cannot find library");
699 mem[nmem++] = obj_add(&oe, path);
700 continue;
702 if (argv[i][1] == 'L') {
703 libdirs[nlibdirs++] = argv[i][2] ? argv[i] + 2 : argv[++i];
704 continue;
706 if (argv[i][1] == 'o') {
707 strcpy(out, argv[i][2] ? argv[i] + 2 : argv[++i]);
708 continue;
710 if (argv[i][1] == 's') {
711 nosyms = 1;
712 continue;
714 if (argv[i][1] == 'g')
715 continue;
716 if (argv[i][1] == 'm') {
717 char sec = argv[i][2];
718 char *arg = argv[i][3] == '=' ? argv[i] + 4 : argv[++i];
719 set_addr(sec, arg);
720 continue;
722 if (argv[i][1] == 'p') {
723 secalign = PAGE_SIZE;
724 continue;
726 if (argv[i][1] == 'e') {
727 entry = argv[i][2] ? argv[i] + 2 : argv[++i];
728 continue;
731 outelf_link(&oe);
732 fd = open(out, O_WRONLY | O_TRUNC | O_CREAT, 0700);
733 outelf_write(&oe, fd);
734 close(fd);
735 for (i = 0; i < nmem; i++)
736 free(mem[i]);
737 return 0;