History

objtool: Add elf_create_file()

Add interface to enable the creation of a new ELF file.

Josh Poimboeuf committed 1 year ago

Commit 03c19a91 parent 2c05ca03 files · +147 −4Browse files

Unified · Split

3 files
  1. tools/objtool/builtin-check.c +1 −1
  2. tools/objtool/elf.c +143 −1
  3. tools/objtool/include/objtool/elf.h +3 −2
tools/objtool/builtin-check.c+1−1
@@ -329,5 +329,5 @@ int objtool_run(int argc, const char **argv) · 328 unmodified lines
329 if (!opts.dryrun && file->elf->changed && elf_write(file->elf))329 if (!opts.dryrun && file->elf->changed && elf_write(file->elf))
330 return 1;330 return 1;
331 331
332 return 0;332 return elf_close(file->elf);
333}333}
tools/objtool/elf.c+143−1
@@ -16,6 +16,7 @@ · 15 unmodified lines
16#include <string.h>16#include <string.h>
17#include <unistd.h>17#include <unistd.h>
18#include <errno.h>18#include <errno.h>
19#include <libgen.h>
19#include <linux/interval_tree_generic.h>20#include <linux/interval_tree_generic.h>
20#include <objtool/builtin.h>21#include <objtool/builtin.h>
21#include <objtool/elf.h>22#include <objtool/elf.h>
@@ -1067,6 +1068,12 @@ struct elf *elf_open_read(const char *name, int flags) · 1045 unmodified lines
1067 goto err;1068 goto err;
1068 }1069 }
1069 1070
1071 elf->name = strdup(name);
1072 if (!elf->name) {
1073 ERROR_GLIBC("strdup");
1074 return NULL;
1075 }
1076
1070 if ((flags & O_ACCMODE) == O_RDONLY)1077 if ((flags & O_ACCMODE) == O_RDONLY)
1071 cmd = ELF_C_READ_MMAP;1078 cmd = ELF_C_READ_MMAP;
1072 else if ((flags & O_ACCMODE) == O_RDWR)1079 else if ((flags & O_ACCMODE) == O_RDWR)
@@ -1104,6 +1111,137 @@ err: · 31 unmodified lines
1104 return NULL;1111 return NULL;
1105}1112}
1106 1113
1114struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name)
1115{
1116 struct section *null, *symtab, *strtab, *shstrtab;
1117 char *dir, *base, *tmp_name;
1118 struct symbol *sym;
1119 struct elf *elf;
1120
1121 elf_version(EV_CURRENT);
1122
1123 elf = calloc(1, sizeof(*elf));
1124 if (!elf) {
1125 ERROR_GLIBC("calloc");
1126 return NULL;
1127 }
1128
1129 INIT_LIST_HEAD(&elf->sections);
1130
1131 dir = strdup(name);
1132 if (!dir) {
1133 ERROR_GLIBC("strdup");
1134 return NULL;
1135 }
1136
1137 dir = dirname(dir);
1138
1139 base = strdup(name);
1140 if (!base) {
1141 ERROR_GLIBC("strdup");
1142 return NULL;
1143 }
1144
1145 base = basename(base);
1146
1147 tmp_name = malloc(256);
1148 if (!tmp_name) {
1149 ERROR_GLIBC("malloc");
1150 return NULL;
1151 }
1152
1153 snprintf(tmp_name, 256, "%s/%s.XXXXXX", dir, base);
1154
1155 elf->fd = mkstemp(tmp_name);
1156 if (elf->fd == -1) {
1157 ERROR_GLIBC("can't create tmp file");
1158 exit(1);
1159 }
1160
1161 elf->tmp_name = tmp_name;
1162
1163 elf->name = strdup(name);
1164 if (!elf->name) {
1165 ERROR_GLIBC("strdup");
1166 return NULL;
1167 }
1168
1169 elf->elf = elf_begin(elf->fd, ELF_C_WRITE, NULL);
1170 if (!elf->elf) {
1171 ERROR_ELF("elf_begin");
1172 return NULL;
1173 }
1174
1175 if (!gelf_newehdr(elf->elf, ELFCLASS64)) {
1176 ERROR_ELF("gelf_newehdr");
1177 return NULL;
1178 }
1179
1180 memcpy(&elf->ehdr, ehdr, sizeof(elf->ehdr));
1181
1182 if (!gelf_update_ehdr(elf->elf, &elf->ehdr)) {
1183 ERROR_ELF("gelf_update_ehdr");
1184 return NULL;
1185 }
1186
1187 if (!elf_alloc_hash(section, 1000) ||
1188 !elf_alloc_hash(section_name, 1000) ||
1189 !elf_alloc_hash(symbol, 10000) ||
1190 !elf_alloc_hash(symbol_name, 10000) ||
1191 !elf_alloc_hash(reloc, 100000))
1192 return NULL;
1193
1194 null = elf_create_section(elf, NULL, 0, 0, SHT_NULL, 0, 0);
1195 shstrtab = elf_create_section(elf, NULL, 0, 0, SHT_STRTAB, 1, 0);
1196 strtab = elf_create_section(elf, NULL, 0, 0, SHT_STRTAB, 1, 0);
1197
1198 if (!null || !shstrtab || !strtab)
1199 return NULL;
1200
1201 null->name = "";
1202 shstrtab->name = ".shstrtab";
1203 strtab->name = ".strtab";
1204
1205 null->sh.sh_name = elf_add_string(elf, shstrtab, null->name);
1206 shstrtab->sh.sh_name = elf_add_string(elf, shstrtab, shstrtab->name);
1207 strtab->sh.sh_name = elf_add_string(elf, shstrtab, strtab->name);
1208
1209 if (null->sh.sh_name == -1 || shstrtab->sh.sh_name == -1 || strtab->sh.sh_name == -1)
1210 return NULL;
1211
1212 elf_hash_add(section_name, &null->name_hash, str_hash(null->name));
1213 elf_hash_add(section_name, &strtab->name_hash, str_hash(strtab->name));
1214 elf_hash_add(section_name, &shstrtab->name_hash, str_hash(shstrtab->name));
1215
1216 if (elf_add_string(elf, strtab, "") == -1)
1217 return NULL;
1218
1219 symtab = elf_create_section(elf, ".symtab", 0x18, 0x18, SHT_SYMTAB, 0x8, 0);
1220 if (!symtab)
1221 return NULL;
1222
1223 symtab->sh.sh_link = strtab->idx;
1224 symtab->sh.sh_info = 1;
1225
1226 elf->ehdr.e_shstrndx = shstrtab->idx;
1227 if (!gelf_update_ehdr(elf->elf, &elf->ehdr)) {
1228 ERROR_ELF("gelf_update_ehdr");
1229 return NULL;
1230 }
1231
1232 sym = calloc(1, sizeof(*sym));
1233 if (!sym) {
1234 ERROR_GLIBC("calloc");
1235 return NULL;
1236 }
1237
1238 sym->name = "";
1239 sym->sec = null;
1240 elf_add_symbol(elf, sym);
1241
1242 return elf;
1243}
1244
1107unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char *str)1245unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char *str)
1108{1246{
1109 unsigned int offset;1247 unsigned int offset;
@@ -1568,7 +1706,7 @@ int elf_write(struct elf *elf) · 458 unmodified lines
1568 return 0;1706 return 0;
1569}1707}
1570 1708
1571void elf_close(struct elf *elf)1709int elf_close(struct elf *elf)
1572{1710{
1573 if (elf->elf)1711 if (elf->elf)
1574 elf_end(elf->elf);1712 elf_end(elf->elf);
@@ -1576,8 +1714,12 @@ void elf_close(struct elf *elf) · 1 unmodified line
1576 if (elf->fd > 0)1714 if (elf->fd > 0)
1577 close(elf->fd);1715 close(elf->fd);
1578 1716
1717 if (elf->tmp_name && rename(elf->tmp_name, elf->name))
1718 return -1;
1719
1579 /*1720 /*
1580 * NOTE: All remaining allocations are leaked on purpose. Objtool is1721 * NOTE: All remaining allocations are leaked on purpose. Objtool is
1581 * about to exit anyway.1722 * about to exit anyway.
1582 */1723 */
1724 return 0;
1583}1725}
tools/objtool/include/objtool/elf.h+3−2
@@ -94,7 +94,7 @@ struct elf { · 93 unmodified lines
94 GElf_Ehdr ehdr;94 GElf_Ehdr ehdr;
95 int fd;95 int fd;
96 bool changed;96 bool changed;
97 const char *name;97 const char *name, *tmp_name;
98 unsigned int num_files;98 unsigned int num_files;
99 struct list_head sections;99 struct list_head sections;
100 unsigned long num_relocs;100 unsigned long num_relocs;
@@ -116,6 +116,7 @@ struct elf { · 15 unmodified lines
116};116};
117 117
118struct elf *elf_open_read(const char *name, int flags);118struct elf *elf_open_read(const char *name, int flags);
119struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name);
119 120
120struct section *elf_create_section(struct elf *elf, const char *name,121struct section *elf_create_section(struct elf *elf, const char *name,
121 size_t size, size_t entsize,122 size_t size, size_t entsize,
@@ -165,7 +166,7 @@ int elf_write_insn(struct elf *elf, struct section *sec, unsigned long offset, · 43 unmodified lines
165 unsigned int len, const char *insn);166 unsigned int len, const char *insn);
166 167
167int elf_write(struct elf *elf);168int elf_write(struct elf *elf);
168void elf_close(struct elf *elf);169int elf_close(struct elf *elf);
169 170
170struct section *find_section_by_name(const struct elf *elf, const char *name);171struct section *find_section_by_name(const struct elf *elf, const char *name);
171struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);172struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t