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
329329 if (!opts.dryrun && file->elf->changed && elf_write(file->elf))
330330 return 1;
331331
332− return 0;
332+ return elf_close(file->elf);
333333 }
tools/objtool/elf.c+143−1
@@ -16,6 +16,7 @@ · 15 unmodified lines
1616 #include <string.h>
1717 #include <unistd.h>
1818 #include <errno.h>
19+#include <libgen.h>
1920 #include <linux/interval_tree_generic.h>
2021 #include <objtool/builtin.h>
2122 #include <objtool/elf.h>
@@ -1067,6 +1068,12 @@ struct elf *elf_open_read(const char *name, int flags) · 1045 unmodified lines
10671068 goto err;
10681069 }
10691070
1071+ elf->name = strdup(name);
1072+ if (!elf->name) {
1073+ ERROR_GLIBC("strdup");
1074+ return NULL;
1075+ }
1076+
10701077 if ((flags & O_ACCMODE) == O_RDONLY)
10711078 cmd = ELF_C_READ_MMAP;
10721079 else if ((flags & O_ACCMODE) == O_RDWR)
@@ -1104,6 +1111,137 @@ err: · 31 unmodified lines
11041111 return NULL;
11051112 }
11061113
1114+struct 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+
11071245 unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char *str)
11081246 {
11091247 unsigned int offset;
@@ -1568,7 +1706,7 @@ int elf_write(struct elf *elf) · 458 unmodified lines
15681706 return 0;
15691707 }
15701708
1571−void elf_close(struct elf *elf)
1709+int elf_close(struct elf *elf)
15721710 {
15731711 if (elf->elf)
15741712 elf_end(elf->elf);
@@ -1576,8 +1714,12 @@ void elf_close(struct elf *elf) · 1 unmodified line
15761714 if (elf->fd > 0)
15771715 close(elf->fd);
15781716
1717+ if (elf->tmp_name && rename(elf->tmp_name, elf->name))
1718+ return -1;
1719+
15791720 /*
15801721 * NOTE: All remaining allocations are leaked on purpose. Objtool is
15811722 * about to exit anyway.
15821723 */
1724+ return 0;
15831725 }
tools/objtool/include/objtool/elf.h+3−2
@@ -94,7 +94,7 @@ struct elf { · 93 unmodified lines
9494 GElf_Ehdr ehdr;
9595 int fd;
9696 bool changed;
97− const char *name;
97+ const char *name, *tmp_name;
9898 unsigned int num_files;
9999 struct list_head sections;
100100 unsigned long num_relocs;
@@ -116,6 +116,7 @@ struct elf { · 15 unmodified lines
116116 };
117117
118118 struct elf *elf_open_read(const char *name, int flags);
119+struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name);
119120
120121 struct section *elf_create_section(struct elf *elf, const char *name,
121122 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
165166 unsigned int len, const char *insn);
166167
167168 int elf_write(struct elf *elf);
168−void elf_close(struct elf *elf);
169+int elf_close(struct elf *elf);
169170
170171 struct section *find_section_by_name(const struct elf *elf, const char *name);
171172 struct 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