Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

objtool: Add elf_create_file()

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

Acked-by: Petr Mladek <pmladek@suse.com>
Tested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

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