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 char dat
[SECSIZE
];
28 static Elf32_Rel datrela
[MAXRELA
];
31 static char buf
[SECSIZE
];
33 static Elf32_Sym
*cur_sym
;
34 static Elf32_Rel rela
[MAXRELA
];
37 static char *putstr(char *s
, char *r
)
45 static int sym_find(char *name
)
48 for (i
= 0; i
< nsyms
; i
++)
49 if (!strcmp(name
, symstr
+ syms
[i
].st_name
))
54 static Elf32_Sym
*put_sym(char *name
)
56 int found
= name
? sym_find(name
) : -1;
57 Elf32_Sym
*sym
= found
!= -1 ? &syms
[found
] : &syms
[nsyms
++];
60 if (name
&& found
== -1) {
61 sym
->st_name
= nsymstr
;
62 nsymstr
= putstr(symstr
+ nsymstr
, name
) - symstr
;
67 #define S_BIND(global) ((global) ? STB_GLOBAL : STB_LOCAL)
69 long out_func_beg(char *name
, int global
)
71 cur_sym
= put_sym(name
);
72 cur_sym
->st_shndx
= SEC_TEXT
;
73 cur_sym
->st_info
= ELF32_ST_INFO(S_BIND(global
), STT_FUNC
);
74 cur_sym
->st_value
= len
;
75 return cur_sym
- syms
;
78 void out_func_end(char *sec
, int sec_len
)
80 memcpy(buf
+ len
, sec
, sec_len
);
82 cur_sym
->st_size
= sec_len
;
85 void out_rela(long addr
, int off
, int rel
)
87 Elf32_Rel
*r
= &rela
[nrela
++];
88 r
->r_offset
= cur_sym
->st_value
+ off
;
89 r
->r_info
= ELF32_R_INFO(addr
, rel
? R_386_PC32
: R_386_32
);
92 void out_datrela(long addr
, long dataddr
, int off
)
94 Elf32_Rel
*r
= &datrela
[ndatrela
++];
95 r
->r_offset
= syms
[dataddr
].st_value
+ off
;
96 r
->r_info
= ELF32_R_INFO(addr
, R_386_32
);
99 #define SYMLOCAL(i) (ELF32_ST_BIND(syms[i].st_info) == STB_LOCAL)
101 static void mvrela(int *mv
, Elf32_Rel
*rela
, int nrela
)
104 for (i
= 0; i
< nrela
; i
++) {
105 int sym
= ELF32_R_SYM(rela
[i
].r_info
);
106 int type
= ELF32_R_TYPE(rela
[i
].r_info
);
107 rela
[i
].r_info
= ELF32_R_INFO(mv
[sym
], type
);
111 static int syms_sort(void)
116 for (i
= 0; i
< nsyms
; i
++)
122 while (i
< j
&& SYMLOCAL(i
))
124 while (j
>= i
&& !SYMLOCAL(j
))
135 mvrela(mv
, rela
, nrela
);
136 mvrela(mv
, datrela
, ndatrela
);
140 void out_write(int fd
)
142 Elf32_Shdr
*text_shdr
= &shdr
[SEC_TEXT
];
143 Elf32_Shdr
*rela_shdr
= &shdr
[SEC_RELA
];
144 Elf32_Shdr
*symstr_shdr
= &shdr
[SEC_SYMSTR
];
145 Elf32_Shdr
*syms_shdr
= &shdr
[SEC_SYMS
];
146 Elf32_Shdr
*dat_shdr
= &shdr
[SEC_DAT
];
147 Elf32_Shdr
*datrela_shdr
= &shdr
[SEC_DATRELA
];
148 Elf32_Shdr
*bss_shdr
= &shdr
[SEC_BSS
];
149 unsigned long offset
= sizeof(ehdr
);
151 ehdr
.e_ident
[0] = 0x7f;
152 ehdr
.e_ident
[1] = 'E';
153 ehdr
.e_ident
[2] = 'L';
154 ehdr
.e_ident
[3] = 'F';
155 ehdr
.e_ident
[4] = ELFCLASS32
;
156 ehdr
.e_ident
[5] = ELFDATA2LSB
;
157 ehdr
.e_ident
[6] = EV_CURRENT
;
158 ehdr
.e_type
= ET_REL
;
159 ehdr
.e_machine
= EM_386
;
160 ehdr
.e_version
= EV_CURRENT
;
161 ehdr
.e_ehsize
= sizeof(ehdr
);
162 ehdr
.e_shentsize
= sizeof(shdr
[0]);
163 ehdr
.e_shoff
= offset
;
164 ehdr
.e_shnum
= NSECS
;
165 ehdr
.e_shstrndx
= SEC_SYMSTR
;
166 offset
+= sizeof(shdr
[0]) * NSECS
;
168 text_shdr
->sh_type
= SHT_PROGBITS
;
169 text_shdr
->sh_flags
= SHF_EXECINSTR
| SHF_ALLOC
;
170 text_shdr
->sh_offset
= offset
;
171 text_shdr
->sh_size
= len
;
172 text_shdr
->sh_entsize
= 1;
173 offset
+= text_shdr
->sh_size
;
175 rela_shdr
->sh_type
= SHT_REL
;
176 rela_shdr
->sh_link
= SEC_SYMS
;
177 rela_shdr
->sh_info
= SEC_TEXT
;
178 rela_shdr
->sh_offset
= offset
;
179 rela_shdr
->sh_size
= nrela
* sizeof(rela
[0]);
180 rela_shdr
->sh_entsize
= sizeof(rela
[0]);
181 offset
+= rela_shdr
->sh_size
;
183 syms_shdr
->sh_type
= SHT_SYMTAB
;
184 syms_shdr
->sh_offset
= offset
;
185 syms_shdr
->sh_size
= nsyms
* sizeof(syms
[0]);
186 syms_shdr
->sh_entsize
= sizeof(syms
[0]);
187 syms_shdr
->sh_link
= SEC_SYMSTR
;
188 syms_shdr
->sh_info
= syms_sort();
189 offset
+= syms_shdr
->sh_size
;
191 dat_shdr
->sh_type
= SHT_PROGBITS
;
192 dat_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
193 dat_shdr
->sh_offset
= offset
;
194 dat_shdr
->sh_size
= datlen
;
195 dat_shdr
->sh_entsize
= 1;
196 dat_shdr
->sh_addralign
= 4;
197 offset
+= dat_shdr
->sh_size
;
199 datrela_shdr
->sh_type
= SHT_REL
;
200 datrela_shdr
->sh_offset
= offset
;
201 datrela_shdr
->sh_size
= ndatrela
* sizeof(datrela
[0]);
202 datrela_shdr
->sh_entsize
= sizeof(datrela
[0]);
203 datrela_shdr
->sh_link
= SEC_SYMS
;
204 datrela_shdr
->sh_info
= SEC_DAT
;
205 offset
+= datrela_shdr
->sh_size
;
207 bss_shdr
->sh_type
= SHT_NOBITS
;
208 bss_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
209 bss_shdr
->sh_offset
= offset
;
210 bss_shdr
->sh_size
= bsslen
;
211 bss_shdr
->sh_entsize
= 1;
212 bss_shdr
->sh_addralign
= 4;
214 symstr_shdr
->sh_type
= SHT_STRTAB
;
215 symstr_shdr
->sh_offset
= offset
;
216 symstr_shdr
->sh_size
= nsymstr
;
217 symstr_shdr
->sh_entsize
= 1;
218 offset
+= symstr_shdr
->sh_size
;
220 write(fd
, &ehdr
, sizeof(ehdr
));
221 write(fd
, shdr
, NSECS
* sizeof(shdr
[0]));
223 write(fd
, rela
, nrela
* sizeof(rela
[0]));
224 write(fd
, syms
, nsyms
* sizeof(syms
[0]));
225 write(fd
, dat
, datlen
);
226 write(fd
, datrela
, ndatrela
* sizeof(datrela
[0]));
227 write(fd
, symstr
, nsymstr
);
230 long out_mkvar(char *name
, int size
, int global
)
232 Elf32_Sym
*sym
= put_sym(name
);
233 sym
->st_shndx
= SEC_BSS
;
234 sym
->st_value
= bsslen
;
236 sym
->st_info
= ELF32_ST_INFO(S_BIND(global
), STT_OBJECT
);
237 bsslen
= ALIGN(bsslen
+ size
, 4);
241 long out_mkundef(char *name
, int sz
)
243 Elf32_Sym
*sym
= put_sym(name
);
244 sym
->st_shndx
= SHN_UNDEF
;
245 sym
->st_info
= ELF32_ST_INFO(STB_GLOBAL
, sz
? STT_OBJECT
: STT_FUNC
);
250 long out_mkdat(char *name
, char *buf
, int len
, int global
)
252 Elf32_Sym
*sym
= put_sym(name
);
253 sym
->st_shndx
= SEC_DAT
;
254 sym
->st_value
= datlen
;
256 sym
->st_info
= ELF32_ST_INFO(S_BIND(global
), STT_OBJECT
);
258 memcpy(dat
+ datlen
, buf
, len
);
260 memset(dat
+ datlen
, 0, len
);
261 datlen
= ALIGN(datlen
+ len
, 4);
265 void out_datcpy(long addr
, int off
, char *buf
, int len
)
267 memcpy(dat
+ syms
[addr
].st_value
+ off
, buf
, len
);