6 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
8 #define MAXSYMS (1 << 12)
9 #define MAXRELA (1 << 12)
19 static Elf32_Ehdr ehdr
;
20 static Elf32_Shdr shdr
[NSECS
];
21 static Elf32_Sym syms
[MAXSYMS
];
23 static char symstr
[MAXSYMS
* 8];
24 static int nsymstr
= 1;
26 static Elf32_Rel datrela
[MAXRELA
];
28 static Elf32_Rel rela
[MAXRELA
];
31 static int symstr_add(char *name
)
33 int len
= strlen(name
) + 1;
34 strcpy(symstr
+ nsymstr
, name
);
39 static int sym_find(char *name
)
42 for (i
= 0; i
< nsyms
; i
++)
43 if (!strcmp(name
, symstr
+ syms
[i
].st_name
))
48 static Elf32_Sym
*put_sym(char *name
)
50 int found
= sym_find(name
);
51 Elf32_Sym
*sym
= found
!= -1 ? &syms
[found
] : &syms
[nsyms
++];
54 sym
->st_name
= symstr_add(name
);
55 sym
->st_shndx
= SHN_UNDEF
;
56 sym
->st_info
= ELF32_ST_INFO(STB_GLOBAL
, STT_FUNC
);
60 #define SYMLOCAL(i) (ELF32_ST_BIND(syms[i].st_info) == STB_LOCAL)
62 static void mvrela(int *mv
, Elf32_Rel
*rela
, int nrela
)
65 for (i
= 0; i
< nrela
; i
++) {
66 int sym
= ELF32_R_SYM(rela
[i
].r_info
);
67 int type
= ELF32_R_TYPE(rela
[i
].r_info
);
68 rela
[i
].r_info
= ELF32_R_INFO(mv
[sym
], type
);
72 static int syms_sort(void)
77 for (i
= 0; i
< nsyms
; i
++)
83 while (i
< j
&& SYMLOCAL(i
))
85 while (j
>= i
&& !SYMLOCAL(j
))
96 mvrela(mv
, rela
, nrela
);
97 mvrela(mv
, datrela
, ndatrela
);
101 void out_init(int flags
)
105 void out_sym(char *name
, int flags
, int off
, int len
)
107 Elf32_Sym
*sym
= put_sym(name
);
108 int type
= (flags
& OUT_CS
) ? STT_FUNC
: STT_OBJECT
;
109 int bind
= (flags
& OUT_GLOB
) ? STB_GLOBAL
: STB_LOCAL
;
111 sym
->st_shndx
= SEC_TEXT
;
113 sym
->st_shndx
= SEC_DAT
;
115 sym
->st_shndx
= SEC_BSS
;
116 sym
->st_info
= ELF32_ST_INFO(bind
, type
);
121 static int rel_type(int flags
)
124 if (flags
& OUT_REL24
)
126 return flags
& OUT_REL
? R_ARM_REL32
: R_ARM_ABS32
;
128 return flags
& OUT_REL
? R_386_PC32
: R_386_32
;
132 static void out_csrel(int idx
, int off
, int flags
)
134 Elf32_Rel
*r
= &rela
[nrela
++];
136 r
->r_info
= ELF32_R_INFO(idx
, rel_type(flags
));
139 static void out_dsrel(int idx
, int off
, int flags
)
141 Elf32_Rel
*r
= &datrela
[ndatrela
++];
143 r
->r_info
= ELF32_R_INFO(idx
, rel_type(flags
));
146 void out_rel(char *name
, int flags
, int off
)
148 Elf32_Sym
*sym
= put_sym(name
);
149 int idx
= sym
- syms
;
151 out_dsrel(idx
, off
, flags
);
153 out_csrel(idx
, off
, flags
);
156 static int bss_len(void)
160 for (i
= 0; i
< nsyms
; i
++) {
161 int end
= syms
[i
].st_value
+ syms
[i
].st_size
;
162 if (syms
[i
].st_shndx
== SEC_BSS
)
169 void out_write(int fd
, char *cs
, int cslen
, char *ds
, int dslen
)
171 Elf32_Shdr
*text_shdr
= &shdr
[SEC_TEXT
];
172 Elf32_Shdr
*rela_shdr
= &shdr
[SEC_RELA
];
173 Elf32_Shdr
*symstr_shdr
= &shdr
[SEC_SYMSTR
];
174 Elf32_Shdr
*syms_shdr
= &shdr
[SEC_SYMS
];
175 Elf32_Shdr
*dat_shdr
= &shdr
[SEC_DAT
];
176 Elf32_Shdr
*datrela_shdr
= &shdr
[SEC_DATRELA
];
177 Elf32_Shdr
*bss_shdr
= &shdr
[SEC_BSS
];
178 unsigned long offset
= sizeof(ehdr
);
180 /* workaround for the idiotic gnuld; use neatld instead! */
181 text_shdr
->sh_name
= symstr_add(".cs");
182 rela_shdr
->sh_name
= symstr_add(".rela.cs");
183 dat_shdr
->sh_name
= symstr_add(".ds");
184 datrela_shdr
->sh_name
= symstr_add(".rela.ds");
186 ehdr
.e_ident
[0] = 0x7f;
187 ehdr
.e_ident
[1] = 'E';
188 ehdr
.e_ident
[2] = 'L';
189 ehdr
.e_ident
[3] = 'F';
190 ehdr
.e_ident
[4] = ELFCLASS32
;
191 ehdr
.e_ident
[5] = ELFDATA2LSB
;
192 ehdr
.e_ident
[6] = EV_CURRENT
;
193 ehdr
.e_type
= ET_REL
;
195 ehdr
.e_machine
= EM_ARM
;
196 ehdr
.e_flags
= EF_ARM_EABI_VER4
;
198 ehdr
.e_machine
= EM_386
;
200 ehdr
.e_version
= EV_CURRENT
;
201 ehdr
.e_ehsize
= sizeof(ehdr
);
202 ehdr
.e_shentsize
= sizeof(shdr
[0]);
203 ehdr
.e_shoff
= offset
;
204 ehdr
.e_shnum
= NSECS
;
205 ehdr
.e_shstrndx
= SEC_SYMSTR
;
206 offset
+= sizeof(shdr
[0]) * NSECS
;
208 text_shdr
->sh_type
= SHT_PROGBITS
;
209 text_shdr
->sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
;
210 text_shdr
->sh_offset
= offset
;
211 text_shdr
->sh_size
= cslen
;
212 text_shdr
->sh_entsize
= 1;
213 text_shdr
->sh_addralign
= OUT_ALIGNMENT
;
214 offset
+= text_shdr
->sh_size
;
216 rela_shdr
->sh_type
= SHT_REL
;
217 rela_shdr
->sh_link
= SEC_SYMS
;
218 rela_shdr
->sh_info
= SEC_TEXT
;
219 rela_shdr
->sh_offset
= offset
;
220 rela_shdr
->sh_size
= nrela
* sizeof(rela
[0]);
221 rela_shdr
->sh_entsize
= sizeof(rela
[0]);
222 offset
+= rela_shdr
->sh_size
;
224 syms_shdr
->sh_type
= SHT_SYMTAB
;
225 syms_shdr
->sh_offset
= offset
;
226 syms_shdr
->sh_size
= nsyms
* sizeof(syms
[0]);
227 syms_shdr
->sh_entsize
= sizeof(syms
[0]);
228 syms_shdr
->sh_link
= SEC_SYMSTR
;
229 syms_shdr
->sh_info
= syms_sort();
230 offset
+= syms_shdr
->sh_size
;
232 dat_shdr
->sh_type
= SHT_PROGBITS
;
233 dat_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
234 dat_shdr
->sh_offset
= offset
;
235 dat_shdr
->sh_size
= dslen
;
236 dat_shdr
->sh_entsize
= 1;
237 dat_shdr
->sh_addralign
= OUT_ALIGNMENT
;
238 offset
+= dat_shdr
->sh_size
;
240 datrela_shdr
->sh_type
= SHT_REL
;
241 datrela_shdr
->sh_offset
= offset
;
242 datrela_shdr
->sh_size
= ndatrela
* sizeof(datrela
[0]);
243 datrela_shdr
->sh_entsize
= sizeof(datrela
[0]);
244 datrela_shdr
->sh_link
= SEC_SYMS
;
245 datrela_shdr
->sh_info
= SEC_DAT
;
246 offset
+= datrela_shdr
->sh_size
;
248 bss_shdr
->sh_type
= SHT_NOBITS
;
249 bss_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
250 bss_shdr
->sh_offset
= offset
;
251 bss_shdr
->sh_size
= bss_len();
252 bss_shdr
->sh_entsize
= 1;
253 bss_shdr
->sh_addralign
= OUT_ALIGNMENT
;
255 symstr_shdr
->sh_type
= SHT_STRTAB
;
256 symstr_shdr
->sh_offset
= offset
;
257 symstr_shdr
->sh_size
= nsymstr
;
258 symstr_shdr
->sh_entsize
= 1;
259 offset
+= symstr_shdr
->sh_size
;
261 write(fd
, &ehdr
, sizeof(ehdr
));
262 write(fd
, shdr
, NSECS
* sizeof(shdr
[0]));
263 write(fd
, cs
, cslen
);
264 write(fd
, rela
, nrela
* sizeof(rela
[0]));
265 write(fd
, syms
, nsyms
* sizeof(syms
[0]));
266 write(fd
, ds
, dslen
);
267 write(fd
, datrela
, ndatrela
* sizeof(datrela
[0]));
268 write(fd
, symstr
, nsymstr
);