6 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
8 #define MAXSECS (1 << 7)
9 #define MAXSYMS (1 << 10)
10 #define MAXRELA (1 << 10)
17 static Elf64_Ehdr ehdr
;
18 static Elf64_Shdr shdr
[MAXSECS
];
19 static int nshdr
= SEC_BEG
;
20 static Elf64_Sym syms
[MAXSYMS
];
22 static char symstr
[MAXSYMS
* 8];
23 static int nsymstr
= 1;
25 static char dat
[SECSIZE
];
32 Elf64_Rela rela
[MAXRELA
];
38 static struct sec
*sec
;
40 static char *putstr(char *s
, char *r
)
48 static int sym_find(char *name
)
51 for (i
= 0; i
< nsyms
; i
++)
52 if (!strcmp(name
, symstr
+ syms
[i
].st_name
))
57 static Elf64_Sym
*put_sym(char *name
)
59 int found
= name
? sym_find(name
) : -1;
60 Elf64_Sym
*sym
= found
!= -1 ? &syms
[found
] : &syms
[nsyms
++];
63 if (name
&& found
== -1) {
64 sym
->st_name
= nsymstr
;
65 nsymstr
= putstr(symstr
+ nsymstr
, name
) - symstr
;
70 #define S_BIND(global) ((global) ? STB_GLOBAL : STB_LOCAL)
72 long out_func_beg(char *name
, int global
)
75 sec
->sym
= put_sym(name
);
76 sec
->sym
->st_shndx
= nshdr
;
77 sec
->sym
->st_info
= ELF64_ST_INFO(S_BIND(global
), STT_FUNC
);
78 sec
->sec_shdr
= &shdr
[nshdr
++];
79 sec
->rel_shdr
= &shdr
[nshdr
++];
80 sec
->rel_shdr
->sh_link
= SEC_SYMS
;
81 sec
->rel_shdr
->sh_info
= sec
->sec_shdr
- shdr
;
82 return sec
->sym
- syms
;
85 void out_func_end(char *buf
, int len
)
87 memcpy(sec
->buf
, buf
, len
);
89 sec
->sym
->st_size
= len
;
92 void out_rela(long addr
, int off
, int rel
)
94 Elf64_Rela
*rela
= &sec
->rela
[sec
->nrela
++];
96 rela
->r_info
= ELF64_R_INFO(addr
, rel
? R_X86_64_PC32
: R_X86_64_32
);
99 #define SYMLOCAL(i) (ELF64_ST_BIND(syms[i].st_info) & STB_LOCAL)
101 static int syms_sort(void)
106 for (i
= 0; i
< nsyms
; i
++)
112 while (j
> i
&& !SYMLOCAL(j
))
114 while (i
< j
&& SYMLOCAL(i
))
125 for (i
= 0; i
< nsecs
; i
++) {
126 for (j
= 0; j
< secs
[i
].nrela
; i
++) {
127 Elf64_Rela
*rela
= &sec
[i
].rela
[j
];
128 int sym
= ELF64_R_SYM(rela
->r_info
);
129 int type
= ELF64_R_TYPE(rela
->r_info
);
130 rela
->r_info
= ELF64_R_INFO(mv
[sym
], type
);
136 void out_write(int fd
)
138 Elf64_Shdr
*symstr_shdr
= &shdr
[SEC_SYMSTR
];
139 Elf64_Shdr
*syms_shdr
= &shdr
[SEC_SYMS
];
140 Elf64_Shdr
*dat_shdr
= &shdr
[SEC_DAT
];
141 Elf64_Shdr
*bss_shdr
= &shdr
[SEC_BSS
];
142 unsigned long offset
= sizeof(ehdr
);
145 ehdr
.e_ident
[0] = 0x7f;
146 ehdr
.e_ident
[1] = 'E';
147 ehdr
.e_ident
[2] = 'L';
148 ehdr
.e_ident
[3] = 'F';
149 ehdr
.e_ident
[4] = ELFCLASS64
;
150 ehdr
.e_ident
[5] = ELFDATA2LSB
;
151 ehdr
.e_ident
[6] = EV_CURRENT
;
152 ehdr
.e_type
= ET_REL
;
153 ehdr
.e_machine
= EM_X86_64
;
154 ehdr
.e_version
= EV_CURRENT
;
155 ehdr
.e_ehsize
= sizeof(ehdr
);
156 ehdr
.e_shentsize
= sizeof(shdr
[0]);
157 ehdr
.e_shoff
= offset
;
158 ehdr
.e_shnum
= nshdr
;
159 ehdr
.e_shstrndx
= SEC_SYMSTR
;
160 offset
+= sizeof(shdr
[0]) * nshdr
;
162 syms_shdr
->sh_type
= SHT_SYMTAB
;
163 syms_shdr
->sh_offset
= offset
;
164 syms_shdr
->sh_size
= nsyms
* sizeof(syms
[0]);
165 syms_shdr
->sh_entsize
= sizeof(syms
[0]);
166 syms_shdr
->sh_link
= SEC_SYMSTR
;
167 syms_shdr
->sh_info
= syms_sort();
168 offset
+= syms_shdr
->sh_size
;
170 dat_shdr
->sh_type
= SHT_PROGBITS
;
171 dat_shdr
->sh_flags
= SHF_WRITE
;
172 dat_shdr
->sh_offset
= offset
;
173 dat_shdr
->sh_size
= datlen
;
174 dat_shdr
->sh_entsize
= 1;
175 dat_shdr
->sh_addralign
= 8;
176 offset
+= dat_shdr
->sh_size
;
178 bss_shdr
->sh_type
= SHT_NOBITS
;
179 bss_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
180 bss_shdr
->sh_offset
= offset
;
181 bss_shdr
->sh_size
= bsslen
;
182 bss_shdr
->sh_entsize
= 1;
183 bss_shdr
->sh_addralign
= 8;
185 symstr_shdr
->sh_type
= SHT_STRTAB
;
186 symstr_shdr
->sh_offset
= offset
;
187 symstr_shdr
->sh_size
= nsymstr
;
188 symstr_shdr
->sh_entsize
= 1;
189 offset
+= symstr_shdr
->sh_size
;
191 for (i
= 0; i
< nsecs
; i
++) {
192 struct sec
*sec
= &secs
[i
];
194 sec
->sec_shdr
->sh_type
= SHT_PROGBITS
;
195 sec
->sec_shdr
->sh_flags
= SHF_EXECINSTR
;
196 sec
->sec_shdr
->sh_offset
= offset
;
197 sec
->sec_shdr
->sh_size
= sec
->len
;
198 sec
->sec_shdr
->sh_entsize
= 1;
199 offset
+= sec
->sec_shdr
->sh_size
;
201 sec
->rel_shdr
->sh_type
= SHT_RELA
;
202 sec
->rel_shdr
->sh_offset
= offset
;
203 sec
->rel_shdr
->sh_size
= sec
->nrela
* sizeof(sec
->rela
[0]);
204 sec
->rel_shdr
->sh_entsize
= sizeof(sec
->rela
[0]);
205 offset
+= sec
->rel_shdr
->sh_size
;
208 write(fd
, &ehdr
, sizeof(ehdr
));
209 write(fd
, shdr
, sizeof(shdr
[0]) * nshdr
);
210 write(fd
, syms
, sizeof(syms
[0]) * nsyms
);
211 write(fd
, dat
, datlen
);
212 write(fd
, symstr
, nsymstr
);
213 for (i
= 0; i
< nsecs
; i
++) {
214 struct sec
*sec
= &secs
[i
];
215 write(fd
, sec
->buf
, sec
->len
);
216 write(fd
, sec
->rela
, sec
->nrela
* sizeof(sec
->rela
[0]));
220 long o_mkvar(char *name
, int size
, int global
)
222 Elf64_Sym
*sym
= put_sym(name
);
223 sym
->st_shndx
= SEC_BSS
;
224 sym
->st_value
= bsslen
;
226 sym
->st_info
= ELF64_ST_INFO(S_BIND(global
), STT_OBJECT
);
227 bsslen
= ALIGN(bsslen
+ size
, 8);
231 long o_mkundef(char *name
)
233 Elf64_Sym
*sym
= put_sym(name
);
234 sym
->st_shndx
= SHN_UNDEF
;
235 sym
->st_info
= ELF64_ST_INFO(STB_GLOBAL
, STT_FUNC
);
239 long o_mkdat(char *name
, char *buf
, int len
, int global
)
241 Elf64_Sym
*sym
= put_sym(name
);
242 sym
->st_shndx
= SEC_DAT
;
243 sym
->st_value
= datlen
;
245 sym
->st_info
= ELF64_ST_INFO(S_BIND(global
), STT_OBJECT
);
246 memcpy(dat
+ datlen
, buf
, len
);
247 datlen
= ALIGN(datlen
+ len
, 8);