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
)
52 for (i
= 0; i
< nsyms
; i
++)
53 if (!strcmp(name
, symstr
+ syms
[i
].st_name
))
58 static Elf64_Sym
*put_sym(char *name
)
60 int found
= name
? sym_find(name
) : -1;
61 Elf64_Sym
*sym
= name
&& found
!= -1 ? &syms
[found
] : &syms
[nsyms
++];
63 if (found
== -1 && name
) {
64 sym
->st_name
= nsymstr
;
65 nsymstr
= putstr(symstr
+ nsymstr
, name
) - symstr
;
67 sym
->st_info
= ELF64_ST_INFO(STB_GLOBAL
, STT_FUNC
);
71 long out_func_beg(char *name
)
74 sec
->sym
= put_sym(name
);
75 sec
->sym
->st_shndx
= nshdr
;
76 sec
->sec_shdr
= &shdr
[nshdr
++];
77 sec
->rel_shdr
= &shdr
[nshdr
++];
78 sec
->rel_shdr
->sh_link
= SEC_SYMS
;
79 sec
->rel_shdr
->sh_info
= sec
->sec_shdr
- shdr
;
80 return sec
->sym
- syms
;
83 void out_func_end(char *buf
, int len
)
85 memcpy(sec
->buf
, buf
, len
);
87 sec
->sym
->st_size
= len
;
90 void out_rela(long addr
, int off
, int rel
)
92 Elf64_Rela
*rela
= &sec
->rela
[sec
->nrela
++];
94 rela
->r_info
= ELF64_R_INFO(addr
, rel
? R_X86_64_PC32
: R_X86_64_32
);
97 void out_write(int fd
)
99 Elf64_Shdr
*symstr_shdr
= &shdr
[SEC_SYMSTR
];
100 Elf64_Shdr
*syms_shdr
= &shdr
[SEC_SYMS
];
101 Elf64_Shdr
*dat_shdr
= &shdr
[SEC_DAT
];
102 Elf64_Shdr
*bss_shdr
= &shdr
[SEC_BSS
];
103 unsigned long offset
= sizeof(ehdr
);
106 ehdr
.e_ident
[0] = 0x7f;
107 ehdr
.e_ident
[1] = 'E';
108 ehdr
.e_ident
[2] = 'L';
109 ehdr
.e_ident
[3] = 'F';
110 ehdr
.e_ident
[4] = ELFCLASS64
;
111 ehdr
.e_ident
[5] = ELFDATA2LSB
;
112 ehdr
.e_ident
[6] = EV_CURRENT
;
113 ehdr
.e_type
= ET_REL
;
114 ehdr
.e_machine
= EM_X86_64
;
115 ehdr
.e_version
= EV_CURRENT
;
116 ehdr
.e_ehsize
= sizeof(ehdr
);
117 ehdr
.e_shentsize
= sizeof(shdr
[0]);
118 ehdr
.e_shoff
= offset
;
119 ehdr
.e_shnum
= nshdr
;
120 ehdr
.e_shstrndx
= SEC_SYMSTR
;
121 offset
+= sizeof(shdr
[0]) * nshdr
;
123 syms_shdr
->sh_type
= SHT_SYMTAB
;
124 syms_shdr
->sh_offset
= offset
;
125 syms_shdr
->sh_size
= nsyms
* sizeof(syms
[0]);
126 syms_shdr
->sh_entsize
= sizeof(syms
[0]);
127 syms_shdr
->sh_link
= SEC_SYMSTR
;
128 offset
+= syms_shdr
->sh_size
;
130 dat_shdr
->sh_type
= SHT_PROGBITS
;
131 dat_shdr
->sh_flags
= SHF_WRITE
;
132 dat_shdr
->sh_offset
= offset
;
133 dat_shdr
->sh_size
= datlen
;
134 dat_shdr
->sh_entsize
= 1;
135 dat_shdr
->sh_addralign
= 8;
136 offset
+= dat_shdr
->sh_size
;
138 bss_shdr
->sh_type
= SHT_NOBITS
;
139 bss_shdr
->sh_flags
= SHF_ALLOC
| SHF_WRITE
;
140 bss_shdr
->sh_offset
= offset
;
141 bss_shdr
->sh_size
= bsslen
;
142 bss_shdr
->sh_entsize
= 1;
143 bss_shdr
->sh_addralign
= 8;
145 symstr_shdr
->sh_type
= SHT_STRTAB
;
146 symstr_shdr
->sh_offset
= offset
;
147 symstr_shdr
->sh_size
= nsymstr
;
148 symstr_shdr
->sh_entsize
= 1;
149 offset
+= symstr_shdr
->sh_size
;
151 for (i
= 0; i
< nsecs
; i
++) {
152 struct sec
*sec
= &secs
[i
];
154 sec
->sec_shdr
->sh_type
= SHT_PROGBITS
;
155 sec
->sec_shdr
->sh_flags
= SHF_EXECINSTR
;
156 sec
->sec_shdr
->sh_offset
= offset
;
157 sec
->sec_shdr
->sh_size
= sec
->len
;
158 sec
->sec_shdr
->sh_entsize
= 1;
159 offset
+= sec
->sec_shdr
->sh_size
;
161 sec
->rel_shdr
->sh_type
= SHT_RELA
;
162 sec
->rel_shdr
->sh_offset
= offset
;
163 sec
->rel_shdr
->sh_size
= sec
->nrela
* sizeof(sec
->rela
[0]);
164 sec
->rel_shdr
->sh_entsize
= sizeof(sec
->rela
[0]);
165 offset
+= sec
->rel_shdr
->sh_size
;
168 write(fd
, &ehdr
, sizeof(ehdr
));
169 write(fd
, shdr
, sizeof(shdr
[0]) * nshdr
);
170 write(fd
, syms
, sizeof(syms
[0]) * nsyms
);
171 write(fd
, dat
, datlen
);
172 write(fd
, symstr
, nsymstr
);
173 for (i
= 0; i
< nsecs
; i
++) {
174 struct sec
*sec
= &secs
[i
];
175 write(fd
, sec
->buf
, sec
->len
);
176 write(fd
, sec
->rela
, sec
->nrela
* sizeof(sec
->rela
[0]));
180 long o_mkvar(char *name
, int size
)
182 Elf64_Sym
*sym
= put_sym(name
);
183 sym
->st_shndx
= SEC_BSS
;
184 sym
->st_value
= bsslen
;
186 sym
->st_info
= ELF64_ST_INFO(STB_GLOBAL
, STT_OBJECT
);
187 bsslen
= ALIGN(bsslen
+ size
, 8);
191 long o_mkundef(char *name
)
193 Elf64_Sym
*sym
= put_sym(name
);
194 sym
->st_shndx
= SHN_UNDEF
;
198 long o_mkdat(char *name
, char *buf
, int len
)
200 Elf64_Sym
*sym
= put_sym(name
);
201 sym
->st_shndx
= SEC_DAT
;
202 sym
->st_value
= datlen
;
204 sym
->st_info
= ELF64_ST_INFO(name
? STB_GLOBAL
: STB_LOCAL
, STT_OBJECT
);
205 memcpy(dat
+ datlen
, buf
, len
);
206 datlen
= ALIGN(datlen
+ len
, 8);