2 * NEATLD ARM/X86(-64) STATIC LINKER
4 * Copyright (C) 2010-2018 Ali Gholami Rudi
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 static unsigned long sec_vaddr
[3] = {0x800000}; /* virtual address of sections */
32 static unsigned long sec_laddr
[3] = {0x800000}; /* load address of sections */
33 static int sec_set
[3] = {1}; /* set address for section */
34 static int secalign
= 16; /* section alignment */
35 static char *entry
= "_start"; /* entry symbol */
36 static int e_machine
; /* target machine */
37 static int e_flags
; /* elf ehdr flags */
39 #define MAXSECS (1 << 10)
40 #define MAXOBJS (1 << 7)
41 #define MAXSYMS (1 << 12)
42 #define PAGE_SIZE (1 << 12)
43 #define PAGE_MASK (PAGE_SIZE - 1)
44 #define MAXFILES (1 << 10)
47 #define MAX(a, b) ((a) > (b) ? (a) : (b))
48 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
50 /* simplified elf struct and macro names */
52 # define Elf_Phdr Elf64_Phdr
53 # define Elf_Ehdr Elf64_Ehdr
54 # define Elf_Shdr Elf64_Shdr
55 # define Elf_Sym Elf64_Sym
56 # define Elf_Rela Elf64_Rela
57 # define SHT_REL_ SHT_RELA
58 # define REL_ADDEND(r) ((r)->r_addend)
59 # define ELF_ST_INFO ELF64_ST_INFO
60 # define ELF_ST_BIND ELF64_ST_BIND
61 # define ELF_R_SYM ELF64_R_SYM
62 # define ELF_R_TYPE ELF64_R_TYPE
63 # define ELF_ST_TYPE ELF64_ST_TYPE
65 # define Elf_Phdr Elf32_Phdr
66 # define Elf_Ehdr Elf32_Ehdr
67 # define Elf_Shdr Elf32_Shdr
68 # define Elf_Sym Elf32_Sym
69 # define Elf_Rela Elf32_Rel
70 # define SHT_REL_ SHT_REL
71 # define REL_ADDEND(r) (0)
72 # define ELF_ST_INFO ELF32_ST_INFO
73 # define ELF_ST_BIND ELF32_ST_BIND
74 # define ELF_R_SYM ELF32_R_SYM
75 # define ELF_R_TYPE ELF32_R_TYPE
76 # define ELF_ST_TYPE ELF32_ST_TYPE
103 Elf_Phdr phdr
[MAXSECS
];
105 struct secmap secs
[MAXSECS
];
107 struct obj objs
[MAXOBJS
];
111 unsigned long code_addr
;
114 struct bss_sym bss_syms
[MAXSYMS
];
116 unsigned long bss_vaddr
;
120 Elf_Shdr shdr
[MAXSECS
];
122 char symstr
[MAXSYMS
];
123 Elf_Sym syms
[MAXSYMS
];
126 unsigned long shdr_faddr
;
127 unsigned long syms_faddr
;
128 unsigned long symstr_faddr
;
131 static int nosyms
= 0;
133 static Elf_Sym
*obj_find(struct obj
*obj
, char *name
)
136 for (i
= 0; i
< obj
->nsyms
; i
++) {
137 Elf_Sym
*sym
= &obj
->syms
[i
];
138 if (ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
||
139 sym
->st_shndx
== SHN_UNDEF
)
141 if (!strcmp(name
, obj
->symstr
+ sym
->st_name
))
147 static void obj_init(struct obj
*obj
, char *mem
)
151 obj
->ehdr
= (void *) mem
;
152 obj
->shdr
= (void *) (mem
+ obj
->ehdr
->e_shoff
);
153 obj
->shstr
= mem
+ obj
->shdr
[obj
->ehdr
->e_shstrndx
].sh_offset
;
154 for (i
= 0; i
< obj
->ehdr
->e_shnum
; i
++) {
155 if (obj
->shdr
[i
].sh_type
!= SHT_SYMTAB
)
157 obj
->symstr
= mem
+ obj
->shdr
[obj
->shdr
[i
].sh_link
].sh_offset
;
158 obj
->syms
= (void *) (mem
+ obj
->shdr
[i
].sh_offset
);
159 obj
->nsyms
= obj
->shdr
[i
].sh_size
/ sizeof(*obj
->syms
);
163 static void outelf_init(struct outelf
*oe
)
165 memset(oe
, 0, sizeof(*oe
));
166 oe
->ehdr
.e_ident
[0] = 0x7f;
167 oe
->ehdr
.e_ident
[1] = 'E';
168 oe
->ehdr
.e_ident
[2] = 'L';
169 oe
->ehdr
.e_ident
[3] = 'F';
170 oe
->ehdr
.e_ident
[4] = sizeof(long) == 8 ? ELFCLASS64
: ELFCLASS32
;
171 oe
->ehdr
.e_ident
[5] = ELFDATA2LSB
;
172 oe
->ehdr
.e_ident
[6] = EV_CURRENT
;
173 oe
->ehdr
.e_type
= ET_EXEC
;
174 oe
->ehdr
.e_version
= EV_CURRENT
;
175 oe
->ehdr
.e_shstrndx
= SHN_UNDEF
;
176 oe
->ehdr
.e_ehsize
= sizeof(oe
->ehdr
);
177 oe
->ehdr
.e_phentsize
= sizeof(oe
->phdr
[0]);
178 oe
->ehdr
.e_shentsize
= sizeof(Elf_Shdr
);
181 static struct secmap
*outelf_mapping(struct outelf
*oe
, Elf_Shdr
*shdr
)
184 for (i
= 0; i
< oe
->nsecs
; i
++)
185 if (oe
->secs
[i
].o_shdr
== shdr
)
190 static int outelf_find(struct outelf
*oe
, char *name
,
191 struct obj
**sym_obj
, Elf_Sym
**sym_sym
)
194 for (i
= 0; i
< oe
->nobjs
; i
++) {
195 struct obj
*obj
= &oe
->objs
[i
];
197 if ((sym
= obj_find(obj
, name
))) {
206 static unsigned long bss_addr(struct outelf
*oe
, Elf_Sym
*sym
)
209 for (i
= 0; i
< oe
->nbss_syms
; i
++)
210 if (oe
->bss_syms
[i
].sym
== sym
)
211 return oe
->bss_vaddr
+ oe
->bss_syms
[i
].off
;
215 static void die(char *msg
)
217 fprintf(stderr
, "%s\n", msg
);
221 static void die_undef(char *name
)
223 fprintf(stderr
, "%s undefined\n", name
);
227 static unsigned long symval(struct outelf
*oe
, struct obj
*obj
, Elf_Sym
*sym
)
230 char *name
= obj
? obj
->symstr
+ sym
->st_name
: NULL
;
232 switch (ELF_ST_TYPE(sym
->st_info
)) {
234 if ((sec
= outelf_mapping(oe
, &obj
->shdr
[sym
->st_shndx
])))
240 if (name
&& *name
&& sym
->st_shndx
== SHN_UNDEF
)
241 if (outelf_find(oe
, name
, &obj
, &sym
))
243 if (sym
->st_shndx
== SHN_COMMON
)
244 return bss_addr(oe
, sym
);
245 s_idx
= sym
->st_shndx
;
246 s_off
= sym
->st_value
;
247 sec
= outelf_mapping(oe
, &obj
->shdr
[s_idx
]);
248 if ((sec
= outelf_mapping(oe
, &obj
->shdr
[s_idx
])))
249 return sec
->vaddr
+ s_off
;
254 static unsigned long outelf_addr(struct outelf
*oe
, char *name
)
258 if (outelf_find(oe
, name
, &obj
, &sym
))
260 return symval(oe
, obj
, sym
);
263 #define REL_ARM 0x10000
264 #define REL_X64 0x20000
265 #define REL_X86 0x40000
267 static int arch_rel(int r
)
269 if (e_machine
== EM_ARM
)
271 if (e_machine
== EM_X86_64
)
273 if (e_machine
== EM_386
)
278 static void outelf_reloc_sec(struct outelf
*oe
, int o_idx
, int s_idx
)
280 struct obj
*obj
= &oe
->objs
[o_idx
];
281 Elf_Shdr
*rel_shdr
= &obj
->shdr
[s_idx
];
282 Elf_Rela
*rels
= (void *) obj
->mem
+ obj
->shdr
[s_idx
].sh_offset
;
283 Elf_Shdr
*other_shdr
= &obj
->shdr
[rel_shdr
->sh_info
];
284 void *other
= (void *) obj
->mem
+ other_shdr
->sh_offset
;
285 int nrels
= rel_shdr
->sh_size
/ sizeof(*rels
);
288 for (i
= 0; i
< nrels
; i
++) {
289 Elf_Rela
*rel
= (void *) &rels
[i
];
290 int sym_idx
= ELF_R_SYM(rel
->r_info
);
291 Elf_Sym
*sym
= &obj
->syms
[sym_idx
];
292 unsigned long val
= symval(oe
, obj
, sym
) + REL_ADDEND(rel
);
293 unsigned long *dst
= other
+ rel
->r_offset
;
294 switch (arch_rel(ELF_R_TYPE(rel
->r_info
))) {
295 case REL_ARM
| R_ARM_NONE
:
296 case REL_X86
| R_386_NONE
:
297 case REL_X64
| R_X86_64_NONE
:
299 case REL_ARM
| R_ARM_ABS16
:
300 case REL_X86
| R_386_16
:
301 case REL_X64
| R_X86_64_16
:
302 *(unsigned short *) dst
+= val
;
304 case REL_ARM
| R_ARM_ABS32
:
305 case REL_X86
| R_386_32
:
306 case REL_X64
| R_X86_64_32
:
307 case REL_X64
| R_X86_64_32S
:
308 *(unsigned int *) dst
+= val
;
310 case REL_X64
| R_X86_64_64
:
313 case REL_ARM
| R_ARM_REL32
:
314 case REL_ARM
| R_ARM_PLT32
:
315 case REL_X86
| R_386_PLT32
:
316 case REL_X86
| R_386_PC32
:
317 case REL_X64
| R_X86_64_PC32
:
318 addr
= outelf_mapping(oe
, other_shdr
)->vaddr
+
320 *(unsigned int *) dst
+= val
- addr
;
322 case REL_ARM
| R_ARM_PC24
:
323 addr
= outelf_mapping(oe
, other_shdr
)->vaddr
+
325 *dst
= (*dst
& 0xff000000) |
326 ((*dst
+ ((val
- addr
) >> 2)) & 0x00ffffff);
329 die("neatld: unknown relocation type!");
334 static void outelf_reloc(struct outelf
*oe
)
337 for (i
= 0; i
< oe
->nobjs
; i
++) {
338 struct obj
*obj
= &oe
->objs
[i
];
339 for (j
= 0; j
< obj
->ehdr
->e_shnum
; j
++)
340 if (obj
->shdr
[j
].sh_type
== SHT_REL_
)
341 outelf_reloc_sec(oe
, i
, j
);
345 static void alloc_bss(struct outelf
*oe
, Elf_Sym
*sym
)
347 int n
= oe
->nbss_syms
++;
348 int off
= ALIGN(oe
->bss_len
, MAX(sym
->st_value
, 4));
349 oe
->bss_syms
[n
].sym
= sym
;
350 oe
->bss_syms
[n
].off
= off
;
351 oe
->bss_len
= off
+ sym
->st_size
;
354 static void outelf_bss(struct outelf
*oe
)
357 for (i
= 0; i
< oe
->nobjs
; i
++) {
358 struct obj
*obj
= &oe
->objs
[i
];
359 for (j
= 0; j
< obj
->nsyms
; j
++)
360 if (obj
->syms
[j
].st_shndx
== SHN_COMMON
)
361 alloc_bss(oe
, &obj
->syms
[j
]);
365 #define SEC_CODE(s) ((s)->sh_flags & SHF_EXECINSTR)
366 #define SEC_BSS(s) ((s)->sh_type == SHT_NOBITS)
367 #define SEC_DATA(s) (!SEC_CODE(s) && !SEC_BSS(s))
369 static char *putstr(char *d
, char *s
)
377 static void build_symtab(struct outelf
*oe
)
380 char *symstr
= oe
->symstr
;
381 Elf_Sym
*syms
= oe
->syms
;
382 Elf_Shdr
*sym_shdr
= &oe
->shdr
[1];
383 Elf_Shdr
*str_shdr
= &oe
->shdr
[2];
385 char *s
= putstr(symstr
, "");
386 int faddr
= oe
->shdr_faddr
;
388 for (i
= 0; i
< oe
->nobjs
; i
++) {
389 struct obj
*obj
= &oe
->objs
[i
];
390 for (j
= 0; j
< obj
->nsyms
; j
++) {
391 Elf_Sym
*sym
= &obj
->syms
[j
];
392 int type
= ELF_ST_TYPE(sym
->st_info
);
393 int bind
= ELF_ST_BIND(sym
->st_info
);
394 char *name
= obj
->symstr
+ sym
->st_name
;
395 if (!*name
|| bind
== STB_LOCAL
||
396 sym
->st_shndx
== SHN_UNDEF
)
398 syms
[n
].st_name
= s
- symstr
;
400 syms
[n
].st_info
= ELF_ST_INFO(bind
, type
);
401 syms
[n
].st_value
= symval(oe
, obj
, sym
);
402 syms
[n
].st_size
= sym
->st_size
;
403 syms
[n
].st_shndx
= SHN_ABS
;
407 oe
->nsymstr
= s
- symstr
;
410 oe
->shdr_faddr
= faddr
;
411 faddr
+= oe
->nsh
* sizeof(oe
->shdr
[0]);
412 oe
->syms_faddr
= faddr
;
413 faddr
+= oe
->nsyms
* sizeof(oe
->syms
[0]);
414 oe
->symstr_faddr
= faddr
;
415 faddr
+= oe
->nsymstr
;
417 oe
->ehdr
.e_shstrndx
= str_shdr
- oe
->shdr
;
418 oe
->ehdr
.e_shoff
= oe
->shdr_faddr
;
419 oe
->ehdr
.e_shnum
= oe
->nsh
;
421 str_shdr
->sh_name
= 0;
422 str_shdr
->sh_type
= SHT_STRTAB
;
423 str_shdr
->sh_offset
= oe
->symstr_faddr
;
424 str_shdr
->sh_size
= oe
->nsymstr
;
426 sym_shdr
->sh_name
= 0;
427 sym_shdr
->sh_type
= SHT_SYMTAB
;
428 sym_shdr
->sh_entsize
= sizeof(oe
->syms
[0]);
429 sym_shdr
->sh_offset
= oe
->syms_faddr
;
430 sym_shdr
->sh_size
= oe
->nsyms
* sizeof(oe
->syms
[0]);
431 sym_shdr
->sh_link
= str_shdr
- oe
->shdr
;
432 sym_shdr
->sh_info
= 0;
435 static void outelf_write(struct outelf
*oe
, int fd
)
438 oe
->ehdr
.e_entry
= outelf_addr(oe
, entry
) -
439 sec_vaddr
[I_CS
] + sec_laddr
[I_CS
];
442 oe
->ehdr
.e_phnum
= oe
->nph
;
443 oe
->ehdr
.e_phoff
= sizeof(oe
->ehdr
);
444 oe
->ehdr
.e_machine
= e_machine
;
445 oe
->ehdr
.e_flags
= e_flags
;
446 lseek(fd
, 0, SEEK_SET
);
447 write(fd
, &oe
->ehdr
, sizeof(oe
->ehdr
));
448 write(fd
, &oe
->phdr
, oe
->nph
* sizeof(oe
->phdr
[0]));
449 for (i
= 0; i
< oe
->nsecs
; i
++) {
450 struct secmap
*sec
= &oe
->secs
[i
];
451 char *buf
= sec
->obj
->mem
+ sec
->o_shdr
->sh_offset
;
452 int len
= sec
->o_shdr
->sh_size
;
453 if (SEC_BSS(sec
->o_shdr
))
455 lseek(fd
, sec
->faddr
, SEEK_SET
);
459 lseek(fd
, oe
->shdr_faddr
, SEEK_SET
);
460 write(fd
, &oe
->shdr
, oe
->nsh
* sizeof(oe
->shdr
[0]));
461 lseek(fd
, oe
->syms_faddr
, SEEK_SET
);
462 write(fd
, &oe
->syms
, oe
->nsyms
* sizeof(oe
->syms
[0]));
463 lseek(fd
, oe
->symstr_faddr
, SEEK_SET
);
464 write(fd
, &oe
->symstr
, oe
->nsymstr
);
468 static void outelf_add(struct outelf
*oe
, char *mem
)
470 Elf_Ehdr
*ehdr
= (void *) mem
;
471 Elf_Shdr
*shdr
= (void *) (mem
+ ehdr
->e_shoff
);
474 if (ehdr
->e_type
!= ET_REL
)
476 e_machine
= ehdr
->e_machine
;
477 e_flags
= ehdr
->e_flags
;
478 if (oe
->nobjs
>= MAXOBJS
)
479 die("neatld: MAXOBJS reached!");
480 obj
= &oe
->objs
[oe
->nobjs
++];
482 for (i
= 0; i
< ehdr
->e_shnum
; i
++) {
484 if (!(shdr
[i
].sh_flags
& 0x7))
486 if (oe
->nsecs
>= MAXSECS
)
487 die("neatld: MAXSECS reached!");
488 sec
= &oe
->secs
[oe
->nsecs
++];
489 sec
->o_shdr
= &shdr
[i
];
494 static int link_cs(struct outelf
*oe
, Elf_Phdr
*phdr
, unsigned long faddr
,
495 unsigned long vaddr
, unsigned long laddr
, int len
)
498 for (i
= 0; i
< oe
->nsecs
; i
++) {
499 struct secmap
*sec
= &oe
->secs
[i
];
500 int alignment
= MAX(sec
->o_shdr
->sh_addralign
, 4);
501 if (!SEC_CODE(sec
->o_shdr
))
503 len
= ALIGN(vaddr
+ len
, alignment
) - vaddr
;
504 sec
->vaddr
= vaddr
+ len
;
505 sec
->faddr
= faddr
+ len
;
506 len
+= sec
->o_shdr
->sh_size
;
508 phdr
->p_type
= PT_LOAD
;
509 phdr
->p_flags
= PF_R
| PF_W
| PF_X
;
510 phdr
->p_vaddr
= vaddr
;
511 phdr
->p_paddr
= laddr
;
512 phdr
->p_offset
= faddr
;
513 phdr
->p_filesz
= len
;
515 phdr
->p_align
= PAGE_SIZE
;
519 static int link_ds(struct outelf
*oe
, Elf_Phdr
*phdr
, unsigned long faddr
,
520 unsigned long vaddr
, unsigned long laddr
)
524 for (i
= 0; i
< oe
->nsecs
; i
++) {
525 struct secmap
*sec
= &oe
->secs
[i
];
526 if (!SEC_DATA(sec
->o_shdr
))
528 sec
->vaddr
= vaddr
+ len
;
529 sec
->faddr
= faddr
+ len
;
530 len
+= sec
->o_shdr
->sh_size
;
533 phdr
->p_type
= PT_LOAD
;
534 phdr
->p_flags
= PF_R
| PF_W
| PF_X
;
535 phdr
->p_align
= PAGE_SIZE
;
536 phdr
->p_vaddr
= vaddr
;
537 phdr
->p_paddr
= laddr
;
538 phdr
->p_filesz
= len
;
540 phdr
->p_offset
= faddr
;
544 static int link_bss(struct outelf
*oe
, Elf_Phdr
*phdr
,
545 unsigned long faddr
, unsigned long vaddr
, int len
)
548 for (i
= 0; i
< oe
->nsecs
; i
++) {
549 struct secmap
*sec
= &oe
->secs
[i
];
550 int alignment
= MAX(sec
->o_shdr
->sh_addralign
, 4);
551 if (!SEC_BSS(sec
->o_shdr
))
553 len
= ALIGN(vaddr
+ len
, alignment
) - vaddr
;
554 sec
->vaddr
= vaddr
+ len
;
556 len
+= sec
->o_shdr
->sh_size
;
558 phdr
->p_type
= PT_LOAD
;
559 phdr
->p_flags
= PF_R
| PF_W
;
560 phdr
->p_vaddr
= vaddr
;
561 phdr
->p_paddr
= vaddr
;
562 phdr
->p_offset
= faddr
;
565 phdr
->p_align
= PAGE_SIZE
;
569 static void outelf_link(struct outelf
*oe
)
571 unsigned long faddr
, vaddr
, laddr
;
573 len
= ALIGN(sizeof(oe
->ehdr
) + MAXPHDRS
* sizeof(oe
->phdr
[0]), secalign
);
574 faddr
= len
& ~PAGE_MASK
;
575 vaddr
= sec_vaddr
[I_CS
];
576 laddr
= sec_laddr
[I_CS
];
577 len
= link_cs(oe
, &oe
->phdr
[0], faddr
, vaddr
, laddr
, len
& PAGE_MASK
);
579 len
= ALIGN(faddr
+ len
, secalign
) - faddr
;
581 vaddr
= sec_set
[I_DS
] ? sec_vaddr
[I_DS
] | (faddr
& PAGE_MASK
) :
582 vaddr
+ PAGE_SIZE
+ len
;
583 laddr
= sec_set
[I_DS
] ? sec_laddr
[I_DS
] | (faddr
& PAGE_MASK
) :
584 laddr
+ PAGE_SIZE
+ len
;
585 len
= link_ds(oe
, &oe
->phdr
[1], faddr
, vaddr
, laddr
);
587 len
= ALIGN(faddr
+ len
, secalign
) - faddr
;
589 vaddr
= sec_set
[I_BSS
] ? sec_vaddr
[I_BSS
] | (faddr
& PAGE_MASK
) :
590 vaddr
+ PAGE_SIZE
+ len
;
592 oe
->bss_vaddr
= vaddr
;
593 len
= link_bss(oe
, &oe
->phdr
[2], faddr
, vaddr
, oe
->bss_len
);
597 oe
->shdr_faddr
= faddr
;
610 static int get_be32(unsigned char *s
)
612 return s
[3] | (s
[2] << 8) | (s
[1] << 16) | (s
[0] << 24);
615 static int sym_undef(struct outelf
*oe
, char *name
)
619 for (i
= 0; i
< oe
->nobjs
; i
++) {
620 struct obj
*obj
= &oe
->objs
[i
];
621 for (j
= 0; j
< obj
->nsyms
; j
++) {
622 Elf_Sym
*sym
= &obj
->syms
[j
];
623 if (ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
)
625 if (strcmp(name
, obj
->symstr
+ sym
->st_name
))
627 if (sym
->st_shndx
!= SHN_UNDEF
)
635 static int outelf_ar_link(struct outelf
*oe
, char *ar
, int base
)
639 int nsyms
= get_be32((void *) ar
);
643 ar_name
= ar_index
+ nsyms
* 4;
644 for (i
= 0; i
< nsyms
; i
++) {
645 int off
= get_be32((void *) ar_index
+ i
* 4) +
646 sizeof(struct arhdr
);
647 if (sym_undef(oe
, ar_name
)) {
648 outelf_add(oe
, ar
- base
+ off
);
651 ar_name
= strchr(ar_name
, '\0') + 1;
656 static void outelf_archive(struct outelf
*oe
, char *ar
)
663 struct arhdr
*hdr
= (void *) ar
;
664 char *name
= hdr
->ar_name
;
667 hdr
->ar_size
[sizeof(hdr
->ar_size
) - 1] = '\0';
668 size
= atoi(hdr
->ar_size
);
669 size
= (size
+ 1) & ~1;
670 if (name
[0] == '/' && name
[1] == ' ') {
671 while (outelf_ar_link(oe
, ar
, ar
- beg
))
675 if (name
[0] == '/' && name
[1] == '/' && name
[2] == ' ')
681 static long filesize(int fd
)
688 static char *fileread(char *path
)
690 int fd
= open(path
, O_RDONLY
);
691 int size
= filesize(fd
);
692 char *buf
= malloc(size
);
698 static int is_ar(char *path
)
700 int len
= strlen(path
);
701 return len
> 2 && path
[len
- 2] == '.' && path
[len
- 1] == 'a';
704 #define LIBDIRS (1 << 5)
705 #define PATHLEN (1 << 8)
707 static char *libdirs
[LIBDIRS
] = {"/lib"};
708 static int nlibdirs
= 1;
710 static int lib_find(char *path
, char *lib
)
714 for (i
= 0; i
< nlibdirs
; i
++) {
715 sprintf(path
, "%s/lib%s.a", libdirs
[i
], lib
);
716 if (!stat(path
, &st
))
722 static unsigned long hexnum(char *s
)
725 if (s
[0] == '0' && s
[1] == 'x')
727 for (; isdigit(*s
) || isalpha(*s
); s
++) {
729 n
|= isdigit(*s
) ? *s
- '0' : tolower(*s
) - 'a' + 10;
734 static void set_addr(int sec
, char *arg
)
737 char *sep
= strchr(arg
, ':');
742 sec_vaddr
[idx
] = hexnum(arg
);
743 sec_laddr
[idx
] = sep
? hexnum(sep
+ 1) : sec_vaddr
[idx
];
747 static char *obj_add(struct outelf
*oe
, char *path
)
749 char *buf
= fileread(path
);
751 die("neatld: cannot open object!");
753 outelf_archive(oe
, buf
);
759 int main(int argc
, char **argv
)
761 char out
[PATHLEN
] = "a.out";
768 die("neatld: no object given!");
772 if (argv
[i
][0] != '-') {
773 mem
[nmem
++] = obj_add(&oe
, argv
[i
]);
776 if (argv
[i
][1] == 'l') {
778 if (lib_find(path
, argv
[i
] + 2))
779 die("neatld: cannot find library!");
780 mem
[nmem
++] = obj_add(&oe
, path
);
783 if (argv
[i
][1] == 'L') {
784 libdirs
[nlibdirs
++] = argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
787 if (argv
[i
][1] == 'o') {
788 strcpy(out
, argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
791 if (argv
[i
][1] == 's') {
795 if (argv
[i
][1] == 'g')
797 if (argv
[i
][1] == 'm') {
798 char sec
= argv
[i
][2];
799 char *arg
= argv
[i
][3] == '=' ? argv
[i
] + 4 : argv
[++i
];
803 if (argv
[i
][1] == 'p') {
804 secalign
= PAGE_SIZE
;
807 if (argv
[i
][1] == 'e') {
808 entry
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
811 if (argv
[i
][1] == 'h') {
812 printf("Usage: neatld [options] objects\n");
817 fd
= open(out
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0700);
819 die("neatld: failed to create the output!");
820 outelf_write(&oe
, fd
);
822 for (i
= 0; i
< nmem
; i
++)