elfedit.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. /* elfedit.c -- Update the ELF header of an ELF format file
  2. Copyright (C) 2010-2022 Free Software Foundation, Inc.
  3. This file is part of GNU Binutils.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
  15. 02110-1301, USA. */
  16. #include "config.h"
  17. #include "sysdep.h"
  18. #include "libiberty.h"
  19. #include <assert.h>
  20. #if __GNUC__ >= 2
  21. /* Define BFD64 here, even if our default architecture is 32 bit ELF
  22. as this will allow us to read in and parse 64bit and 32bit ELF files.
  23. Only do this if we believe that the compiler can support a 64 bit
  24. data type. For now we only rely on GCC being able to do this. */
  25. #define BFD64
  26. #endif
  27. #include "bfd.h"
  28. #include "elfcomm.h"
  29. #include "bucomm.h"
  30. #include "elf/common.h"
  31. #include "elf/external.h"
  32. #include "elf/internal.h"
  33. #include "getopt.h"
  34. #include "libiberty.h"
  35. #include "safe-ctype.h"
  36. #include "filenames.h"
  37. char * program_name = "elfedit";
  38. static long archive_file_offset;
  39. static unsigned long archive_file_size;
  40. static Elf_Internal_Ehdr elf_header;
  41. static Elf32_External_Ehdr ehdr32;
  42. static Elf64_External_Ehdr ehdr64;
  43. static int input_elf_machine = -1;
  44. static int output_elf_machine = -1;
  45. static int input_elf_type = -1;
  46. static int output_elf_type = -1;
  47. static int input_elf_osabi = -1;
  48. static int output_elf_osabi = -1;
  49. static int input_elf_abiversion = -1;
  50. static int output_elf_abiversion = -1;
  51. enum elfclass
  52. {
  53. ELF_CLASS_UNKNOWN = -1,
  54. ELF_CLASS_NONE = ELFCLASSNONE,
  55. ELF_CLASS_32 = ELFCLASS32,
  56. ELF_CLASS_64 = ELFCLASS64,
  57. ELF_CLASS_BOTH
  58. };
  59. static enum elfclass input_elf_class = ELF_CLASS_UNKNOWN;
  60. static enum elfclass output_elf_class = ELF_CLASS_BOTH;
  61. #ifdef HAVE_MMAP
  62. #include <sys/mman.h>
  63. static unsigned int enable_x86_features;
  64. static unsigned int disable_x86_features;
  65. static int
  66. update_gnu_property (const char *file_name, FILE *file)
  67. {
  68. char *map;
  69. Elf_Internal_Phdr *phdrs;
  70. struct stat st_buf;
  71. unsigned int i;
  72. int ret;
  73. if (!enable_x86_features && !disable_x86_features)
  74. return 0;
  75. if (elf_header.e_machine != EM_386
  76. && elf_header.e_machine != EM_X86_64)
  77. {
  78. error (_("%s: Not an i386 nor x86-64 ELF file\n"), file_name);
  79. return 0;
  80. }
  81. if (fstat (fileno (file), &st_buf) < 0)
  82. {
  83. error (_("%s: stat () failed\n"), file_name);
  84. return 1;
  85. }
  86. map = mmap (NULL, st_buf.st_size, PROT_READ | PROT_WRITE,
  87. MAP_SHARED, fileno (file), 0);
  88. if (map == MAP_FAILED)
  89. {
  90. error (_("%s: mmap () failed\n"), file_name);
  91. return 0;
  92. }
  93. phdrs = xmalloc (elf_header.e_phnum * sizeof (*phdrs));
  94. if (elf_header.e_ident[EI_CLASS] == ELFCLASS32)
  95. {
  96. Elf32_External_Phdr *phdrs32
  97. = (Elf32_External_Phdr *) (map + elf_header.e_phoff);
  98. for (i = 0; i < elf_header.e_phnum; i++)
  99. {
  100. phdrs[i].p_type = BYTE_GET (phdrs32[i].p_type);
  101. phdrs[i].p_offset = BYTE_GET (phdrs32[i].p_offset);
  102. phdrs[i].p_vaddr = BYTE_GET (phdrs32[i].p_vaddr);
  103. phdrs[i].p_paddr = BYTE_GET (phdrs32[i].p_paddr);
  104. phdrs[i].p_filesz = BYTE_GET (phdrs32[i].p_filesz);
  105. phdrs[i].p_memsz = BYTE_GET (phdrs32[i].p_memsz);
  106. phdrs[i].p_flags = BYTE_GET (phdrs32[i].p_flags);
  107. phdrs[i].p_align = BYTE_GET (phdrs32[i].p_align);
  108. }
  109. }
  110. else
  111. {
  112. Elf64_External_Phdr *phdrs64
  113. = (Elf64_External_Phdr *) (map + elf_header.e_phoff);
  114. for (i = 0; i < elf_header.e_phnum; i++)
  115. {
  116. phdrs[i].p_type = BYTE_GET (phdrs64[i].p_type);
  117. phdrs[i].p_offset = BYTE_GET (phdrs64[i].p_offset);
  118. phdrs[i].p_vaddr = BYTE_GET (phdrs64[i].p_vaddr);
  119. phdrs[i].p_paddr = BYTE_GET (phdrs64[i].p_paddr);
  120. phdrs[i].p_filesz = BYTE_GET (phdrs64[i].p_filesz);
  121. phdrs[i].p_memsz = BYTE_GET (phdrs64[i].p_memsz);
  122. phdrs[i].p_flags = BYTE_GET (phdrs64[i].p_flags);
  123. phdrs[i].p_align = BYTE_GET (phdrs64[i].p_align);
  124. }
  125. }
  126. ret = 0;
  127. for (i = 0; i < elf_header.e_phnum; i++)
  128. if (phdrs[i].p_type == PT_NOTE)
  129. {
  130. size_t offset = phdrs[i].p_offset;
  131. size_t size = phdrs[i].p_filesz;
  132. size_t align = phdrs[i].p_align;
  133. char *buf = map + offset;
  134. char *p = buf;
  135. while (p < buf + size)
  136. {
  137. Elf_External_Note *xnp = (Elf_External_Note *) p;
  138. Elf_Internal_Note in;
  139. if (offsetof (Elf_External_Note, name) > buf - p + size)
  140. {
  141. ret = 1;
  142. goto out;
  143. }
  144. in.type = BYTE_GET (xnp->type);
  145. in.namesz = BYTE_GET (xnp->namesz);
  146. in.namedata = xnp->name;
  147. if (in.namesz > buf - in.namedata + size)
  148. {
  149. ret = 1;
  150. goto out;
  151. }
  152. in.descsz = BYTE_GET (xnp->descsz);
  153. in.descdata = p + ELF_NOTE_DESC_OFFSET (in.namesz, align);
  154. in.descpos = offset + (in.descdata - buf);
  155. if (in.descsz != 0
  156. && (in.descdata >= buf + size
  157. || in.descsz > buf - in.descdata + size))
  158. {
  159. ret = 1;
  160. goto out;
  161. }
  162. if (in.namesz == sizeof "GNU"
  163. && strcmp (in.namedata, "GNU") == 0
  164. && in.type == NT_GNU_PROPERTY_TYPE_0)
  165. {
  166. unsigned char *ptr;
  167. unsigned char *ptr_end;
  168. if (in.descsz < 8 || (in.descsz % align) != 0)
  169. {
  170. ret = 1;
  171. goto out;
  172. }
  173. ptr = (unsigned char *) in.descdata;
  174. ptr_end = ptr + in.descsz;
  175. do
  176. {
  177. unsigned int type = byte_get (ptr, 4);
  178. unsigned int datasz = byte_get (ptr + 4, 4);
  179. unsigned int bitmask, old_bitmask;
  180. ptr += 8;
  181. if ((ptr + datasz) > ptr_end)
  182. {
  183. ret = 1;
  184. goto out;
  185. }
  186. if (type == GNU_PROPERTY_X86_FEATURE_1_AND)
  187. {
  188. if (datasz != 4)
  189. {
  190. ret = 1;
  191. goto out;
  192. }
  193. old_bitmask = byte_get (ptr, 4);
  194. bitmask = old_bitmask;
  195. if (enable_x86_features)
  196. bitmask |= enable_x86_features;
  197. if (disable_x86_features)
  198. bitmask &= ~disable_x86_features;
  199. if (old_bitmask != bitmask)
  200. byte_put (ptr, bitmask, 4);
  201. goto out;
  202. }
  203. ptr += ELF_ALIGN_UP (datasz, align);
  204. }
  205. while ((ptr_end - ptr) >= 8);
  206. }
  207. p += ELF_NOTE_NEXT_OFFSET (in.namesz, in.descsz, align);
  208. }
  209. }
  210. out:
  211. if (ret != 0)
  212. error (_("%s: Invalid PT_NOTE segment\n"), file_name);
  213. free (phdrs);
  214. munmap (map, st_buf.st_size);
  215. return ret;
  216. }
  217. /* Set enable_x86_features and disable_x86_features for a feature
  218. string, FEATURE. */
  219. static int
  220. elf_x86_feature (const char *feature, int enable)
  221. {
  222. unsigned int x86_feature;
  223. if (strcasecmp (feature, "ibt") == 0)
  224. x86_feature = GNU_PROPERTY_X86_FEATURE_1_IBT;
  225. else if (strcasecmp (feature, "shstk") == 0)
  226. x86_feature = GNU_PROPERTY_X86_FEATURE_1_SHSTK;
  227. else if (strcasecmp (feature, "lam_u48") == 0)
  228. x86_feature = GNU_PROPERTY_X86_FEATURE_1_LAM_U48;
  229. else if (strcasecmp (feature, "lam_u57") == 0)
  230. x86_feature = GNU_PROPERTY_X86_FEATURE_1_LAM_U57;
  231. else
  232. {
  233. error (_("Unknown x86 feature: %s\n"), feature);
  234. return -1;
  235. }
  236. if (enable)
  237. {
  238. enable_x86_features |= x86_feature;
  239. disable_x86_features &= ~x86_feature;
  240. }
  241. else
  242. {
  243. disable_x86_features |= x86_feature;
  244. enable_x86_features &= ~x86_feature;
  245. }
  246. return 0;
  247. }
  248. #endif
  249. /* Return ELF class for a machine type, MACH. */
  250. static enum elfclass
  251. elf_class (int mach)
  252. {
  253. switch (mach)
  254. {
  255. case EM_386:
  256. case EM_IAMCU:
  257. return ELF_CLASS_32;
  258. case EM_L1OM:
  259. case EM_K1OM:
  260. return ELF_CLASS_64;
  261. case EM_X86_64:
  262. case EM_NONE:
  263. return ELF_CLASS_BOTH;
  264. default:
  265. return ELF_CLASS_BOTH;
  266. }
  267. }
  268. static int
  269. update_elf_header (const char *file_name, FILE *file)
  270. {
  271. int class, machine, type, status, osabi, abiversion;
  272. if (elf_header.e_ident[EI_VERSION] != EV_CURRENT)
  273. {
  274. error
  275. (_("%s: Unsupported EI_VERSION: %d is not %d\n"),
  276. file_name, elf_header.e_ident[EI_VERSION],
  277. EV_CURRENT);
  278. return 0;
  279. }
  280. /* Return if e_machine is the same as output_elf_machine. */
  281. if (output_elf_machine == elf_header.e_machine)
  282. return 1;
  283. class = elf_header.e_ident[EI_CLASS];
  284. machine = elf_header.e_machine;
  285. /* Skip if class doesn't match. */
  286. if (input_elf_class == ELF_CLASS_UNKNOWN)
  287. input_elf_class = elf_class (machine);
  288. if (input_elf_class != ELF_CLASS_BOTH
  289. && (int) input_elf_class != class)
  290. {
  291. error
  292. (_("%s: Unmatched input EI_CLASS: %d is not %d\n"),
  293. file_name, class, input_elf_class);
  294. return 0;
  295. }
  296. if (output_elf_class != ELF_CLASS_BOTH
  297. && (int) output_elf_class != class)
  298. {
  299. error
  300. (_("%s: Unmatched output EI_CLASS: %d is not %d\n"),
  301. file_name, class, output_elf_class);
  302. return 0;
  303. }
  304. /* Skip if e_machine doesn't match. */
  305. if (input_elf_machine != -1 && machine != input_elf_machine)
  306. {
  307. error
  308. (_("%s: Unmatched e_machine: %d is not %d\n"),
  309. file_name, machine, input_elf_machine);
  310. return 0;
  311. }
  312. type = elf_header.e_type;
  313. /* Skip if e_type doesn't match. */
  314. if (input_elf_type != -1 && type != input_elf_type)
  315. {
  316. error
  317. (_("%s: Unmatched e_type: %d is not %d\n"),
  318. file_name, type, input_elf_type);
  319. return 0;
  320. }
  321. osabi = elf_header.e_ident[EI_OSABI];
  322. /* Skip if OSABI doesn't match. */
  323. if (input_elf_osabi != -1 && osabi != input_elf_osabi)
  324. {
  325. error
  326. (_("%s: Unmatched EI_OSABI: %d is not %d\n"),
  327. file_name, osabi, input_elf_osabi);
  328. return 0;
  329. }
  330. abiversion = elf_header.e_ident[EI_ABIVERSION];
  331. /* Skip if ABIVERSION doesn't match. */
  332. if (input_elf_abiversion != -1
  333. && abiversion != input_elf_abiversion)
  334. {
  335. error
  336. (_("%s: Unmatched EI_ABIVERSION: %d is not %d\n"),
  337. file_name, abiversion, input_elf_abiversion);
  338. return 0;
  339. }
  340. /* Update e_machine, e_type and EI_OSABI. */
  341. switch (class)
  342. {
  343. default:
  344. /* We should never get here. */
  345. abort ();
  346. break;
  347. case ELFCLASS32:
  348. if (output_elf_machine != -1)
  349. BYTE_PUT (ehdr32.e_machine, output_elf_machine);
  350. if (output_elf_type != -1)
  351. BYTE_PUT (ehdr32.e_type, output_elf_type);
  352. if (output_elf_osabi != -1)
  353. ehdr32.e_ident[EI_OSABI] = output_elf_osabi;
  354. if (output_elf_abiversion != -1)
  355. ehdr32.e_ident[EI_ABIVERSION] = output_elf_abiversion;
  356. status = fwrite (&ehdr32, sizeof (ehdr32), 1, file) == 1;
  357. break;
  358. case ELFCLASS64:
  359. if (output_elf_machine != -1)
  360. BYTE_PUT (ehdr64.e_machine, output_elf_machine);
  361. if (output_elf_type != -1)
  362. BYTE_PUT (ehdr64.e_type, output_elf_type);
  363. if (output_elf_osabi != -1)
  364. ehdr64.e_ident[EI_OSABI] = output_elf_osabi;
  365. if (output_elf_abiversion != -1)
  366. ehdr64.e_ident[EI_ABIVERSION] = output_elf_abiversion;
  367. status = fwrite (&ehdr64, sizeof (ehdr64), 1, file) == 1;
  368. break;
  369. }
  370. if (status != 1)
  371. error (_("%s: Failed to update ELF header: %s\n"),
  372. file_name, strerror (errno));
  373. return status;
  374. }
  375. static int
  376. get_file_header (FILE * file)
  377. {
  378. /* Read in the identity array. */
  379. if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
  380. return 0;
  381. if (elf_header.e_ident[EI_MAG0] != ELFMAG0
  382. || elf_header.e_ident[EI_MAG1] != ELFMAG1
  383. || elf_header.e_ident[EI_MAG2] != ELFMAG2
  384. || elf_header.e_ident[EI_MAG3] != ELFMAG3)
  385. return 0;
  386. /* Determine how to read the rest of the header. */
  387. switch (elf_header.e_ident[EI_DATA])
  388. {
  389. default: /* fall through */
  390. case ELFDATANONE: /* fall through */
  391. case ELFDATA2LSB:
  392. byte_get = byte_get_little_endian;
  393. byte_put = byte_put_little_endian;
  394. break;
  395. case ELFDATA2MSB:
  396. byte_get = byte_get_big_endian;
  397. byte_put = byte_put_big_endian;
  398. break;
  399. }
  400. /* Read in the rest of the header. For now we only support 32 bit
  401. and 64 bit ELF files. */
  402. switch (elf_header.e_ident[EI_CLASS])
  403. {
  404. default:
  405. return 0;
  406. case ELFCLASS32:
  407. if (fread (ehdr32.e_type, sizeof (ehdr32) - EI_NIDENT,
  408. 1, file) != 1)
  409. return 0;
  410. elf_header.e_type = BYTE_GET (ehdr32.e_type);
  411. elf_header.e_machine = BYTE_GET (ehdr32.e_machine);
  412. elf_header.e_version = BYTE_GET (ehdr32.e_version);
  413. elf_header.e_entry = BYTE_GET (ehdr32.e_entry);
  414. elf_header.e_phoff = BYTE_GET (ehdr32.e_phoff);
  415. elf_header.e_shoff = BYTE_GET (ehdr32.e_shoff);
  416. elf_header.e_flags = BYTE_GET (ehdr32.e_flags);
  417. elf_header.e_ehsize = BYTE_GET (ehdr32.e_ehsize);
  418. elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
  419. elf_header.e_phnum = BYTE_GET (ehdr32.e_phnum);
  420. elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
  421. elf_header.e_shnum = BYTE_GET (ehdr32.e_shnum);
  422. elf_header.e_shstrndx = BYTE_GET (ehdr32.e_shstrndx);
  423. memcpy (&ehdr32, &elf_header, EI_NIDENT);
  424. break;
  425. case ELFCLASS64:
  426. /* If we have been compiled with sizeof (bfd_vma) == 4, then
  427. we will not be able to cope with the 64bit data found in
  428. 64 ELF files. Detect this now and abort before we start
  429. overwriting things. */
  430. if (sizeof (bfd_vma) < 8)
  431. {
  432. error (_("This executable has been built without support for a\n\
  433. 64 bit data type and so it cannot process 64 bit ELF files.\n"));
  434. return 0;
  435. }
  436. if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT,
  437. 1, file) != 1)
  438. return 0;
  439. elf_header.e_type = BYTE_GET (ehdr64.e_type);
  440. elf_header.e_machine = BYTE_GET (ehdr64.e_machine);
  441. elf_header.e_version = BYTE_GET (ehdr64.e_version);
  442. elf_header.e_entry = BYTE_GET (ehdr64.e_entry);
  443. elf_header.e_phoff = BYTE_GET (ehdr64.e_phoff);
  444. elf_header.e_shoff = BYTE_GET (ehdr64.e_shoff);
  445. elf_header.e_flags = BYTE_GET (ehdr64.e_flags);
  446. elf_header.e_ehsize = BYTE_GET (ehdr64.e_ehsize);
  447. elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
  448. elf_header.e_phnum = BYTE_GET (ehdr64.e_phnum);
  449. elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
  450. elf_header.e_shnum = BYTE_GET (ehdr64.e_shnum);
  451. elf_header.e_shstrndx = BYTE_GET (ehdr64.e_shstrndx);
  452. memcpy (&ehdr64, &elf_header, EI_NIDENT);
  453. break;
  454. }
  455. return 1;
  456. }
  457. /* Process one ELF object file according to the command line options.
  458. This file may actually be stored in an archive. The file is
  459. positioned at the start of the ELF object. */
  460. static int
  461. process_object (const char *file_name, FILE *file)
  462. {
  463. /* Rememeber where we are. */
  464. long offset = ftell (file);
  465. if (! get_file_header (file))
  466. {
  467. error (_("%s: Failed to read ELF header\n"), file_name);
  468. return 1;
  469. }
  470. /* Go to the position of the ELF header. */
  471. if (fseek (file, offset, SEEK_SET) != 0)
  472. {
  473. error (_("%s: Failed to seek to ELF header\n"), file_name);
  474. }
  475. if (! update_elf_header (file_name, file))
  476. return 1;
  477. return 0;
  478. }
  479. /* Process an ELF archive.
  480. On entry the file is positioned just after the ARMAG string. */
  481. static int
  482. process_archive (const char * file_name, FILE * file,
  483. bool is_thin_archive)
  484. {
  485. struct archive_info arch;
  486. struct archive_info nested_arch;
  487. size_t got;
  488. int ret;
  489. struct stat statbuf;
  490. /* The ARCH structure is used to hold information about this archive. */
  491. arch.file_name = NULL;
  492. arch.file = NULL;
  493. arch.index_array = NULL;
  494. arch.sym_table = NULL;
  495. arch.longnames = NULL;
  496. /* The NESTED_ARCH structure is used as a single-item cache of information
  497. about a nested archive (when members of a thin archive reside within
  498. another regular archive file). */
  499. nested_arch.file_name = NULL;
  500. nested_arch.file = NULL;
  501. nested_arch.index_array = NULL;
  502. nested_arch.sym_table = NULL;
  503. nested_arch.longnames = NULL;
  504. if (fstat (fileno (file), &statbuf) < 0
  505. || setup_archive (&arch, file_name, file, statbuf.st_size,
  506. is_thin_archive, false) != 0)
  507. {
  508. ret = 1;
  509. goto out;
  510. }
  511. ret = 0;
  512. while (1)
  513. {
  514. char * name;
  515. size_t namelen;
  516. char * qualified_name;
  517. /* Read the next archive header. */
  518. if (fseek (file, arch.next_arhdr_offset, SEEK_SET) != 0)
  519. {
  520. error (_("%s: failed to seek to next archive header\n"),
  521. file_name);
  522. return 1;
  523. }
  524. got = fread (&arch.arhdr, 1, sizeof arch.arhdr, file);
  525. if (got != sizeof arch.arhdr)
  526. {
  527. if (got == 0)
  528. break;
  529. error (_("%s: failed to read archive header\n"),
  530. file_name);
  531. ret = 1;
  532. break;
  533. }
  534. if (memcmp (arch.arhdr.ar_fmag, ARFMAG, 2) != 0)
  535. {
  536. error (_("%s: did not find a valid archive header\n"),
  537. arch.file_name);
  538. ret = 1;
  539. break;
  540. }
  541. arch.next_arhdr_offset += sizeof arch.arhdr;
  542. archive_file_size = strtoul (arch.arhdr.ar_size, NULL, 10);
  543. if (archive_file_size & 01)
  544. ++archive_file_size;
  545. name = get_archive_member_name (&arch, &nested_arch);
  546. if (name == NULL)
  547. {
  548. error (_("%s: bad archive file name\n"), file_name);
  549. ret = 1;
  550. break;
  551. }
  552. namelen = strlen (name);
  553. qualified_name = make_qualified_name (&arch, &nested_arch, name);
  554. if (qualified_name == NULL)
  555. {
  556. error (_("%s: bad archive file name\n"), file_name);
  557. free (name);
  558. ret = 1;
  559. break;
  560. }
  561. if (is_thin_archive && arch.nested_member_origin == 0)
  562. {
  563. /* This is a proxy for an external member of a thin archive. */
  564. FILE *member_file;
  565. char *member_file_name = adjust_relative_path (file_name,
  566. name, namelen);
  567. free (name);
  568. if (member_file_name == NULL)
  569. {
  570. free (qualified_name);
  571. ret = 1;
  572. break;
  573. }
  574. member_file = fopen (member_file_name, "r+b");
  575. if (member_file == NULL)
  576. {
  577. error (_("Input file '%s' is not readable\n"),
  578. member_file_name);
  579. free (member_file_name);
  580. free (qualified_name);
  581. ret = 1;
  582. break;
  583. }
  584. archive_file_offset = arch.nested_member_origin;
  585. ret |= process_object (qualified_name, member_file);
  586. fclose (member_file);
  587. free (member_file_name);
  588. }
  589. else if (is_thin_archive)
  590. {
  591. free (name);
  592. /* This is a proxy for a member of a nested archive. */
  593. archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
  594. /* The nested archive file will have been opened and setup by
  595. get_archive_member_name. */
  596. if (fseek (nested_arch.file, archive_file_offset,
  597. SEEK_SET) != 0)
  598. {
  599. error (_("%s: failed to seek to archive member\n"),
  600. nested_arch.file_name);
  601. free (qualified_name);
  602. ret = 1;
  603. break;
  604. }
  605. ret |= process_object (qualified_name, nested_arch.file);
  606. }
  607. else
  608. {
  609. free (name);
  610. archive_file_offset = arch.next_arhdr_offset;
  611. arch.next_arhdr_offset += archive_file_size;
  612. ret |= process_object (qualified_name, file);
  613. }
  614. free (qualified_name);
  615. }
  616. out:
  617. if (nested_arch.file != NULL)
  618. fclose (nested_arch.file);
  619. release_archive (&nested_arch);
  620. release_archive (&arch);
  621. return ret;
  622. }
  623. static int
  624. check_file (const char *file_name, struct stat *statbuf_p)
  625. {
  626. struct stat statbuf;
  627. if (statbuf_p == NULL)
  628. statbuf_p = &statbuf;
  629. if (stat (file_name, statbuf_p) < 0)
  630. {
  631. if (errno == ENOENT)
  632. error (_("'%s': No such file\n"), file_name);
  633. else
  634. error (_("Could not locate '%s'. System error message: %s\n"),
  635. file_name, strerror (errno));
  636. return 1;
  637. }
  638. #if defined (_WIN32) && !defined (__CYGWIN__)
  639. else if (statbuf_p->st_size == 0)
  640. {
  641. /* MS-Windows 'stat' reports the null device as a regular file;
  642. fix that. */
  643. int fd = open (file_name, O_RDONLY | O_BINARY);
  644. if (isatty (fd))
  645. {
  646. statbuf_p->st_mode &= ~S_IFREG;
  647. statbuf_p->st_mode |= S_IFCHR;
  648. }
  649. }
  650. #endif
  651. if (! S_ISREG (statbuf_p->st_mode))
  652. {
  653. error (_("'%s' is not an ordinary file\n"), file_name);
  654. return 1;
  655. }
  656. return 0;
  657. }
  658. static int
  659. process_file (const char *file_name)
  660. {
  661. FILE * file;
  662. char armag[SARMAG];
  663. int ret;
  664. if (check_file (file_name, NULL))
  665. return 1;
  666. file = fopen (file_name, "r+b");
  667. if (file == NULL)
  668. {
  669. error (_("Input file '%s' is not readable\n"), file_name);
  670. return 1;
  671. }
  672. if (fread (armag, SARMAG, 1, file) != 1)
  673. {
  674. error (_("%s: Failed to read file's magic number\n"),
  675. file_name);
  676. fclose (file);
  677. return 1;
  678. }
  679. if (memcmp (armag, ARMAG, SARMAG) == 0)
  680. ret = process_archive (file_name, file, false);
  681. else if (memcmp (armag, ARMAGT, SARMAG) == 0)
  682. ret = process_archive (file_name, file, true);
  683. else
  684. {
  685. rewind (file);
  686. archive_file_size = archive_file_offset = 0;
  687. ret = process_object (file_name, file);
  688. #ifdef HAVE_MMAP
  689. if (!ret
  690. && (elf_header.e_type == ET_EXEC
  691. || elf_header.e_type == ET_DYN))
  692. ret = update_gnu_property (file_name, file);
  693. #endif
  694. }
  695. fclose (file);
  696. return ret;
  697. }
  698. static const struct
  699. {
  700. int osabi;
  701. const char *name;
  702. }
  703. osabis[] =
  704. {
  705. { ELFOSABI_NONE, "none" },
  706. { ELFOSABI_HPUX, "HPUX" },
  707. { ELFOSABI_NETBSD, "NetBSD" },
  708. { ELFOSABI_GNU, "GNU" },
  709. { ELFOSABI_GNU, "Linux" },
  710. { ELFOSABI_SOLARIS, "Solaris" },
  711. { ELFOSABI_AIX, "AIX" },
  712. { ELFOSABI_IRIX, "Irix" },
  713. { ELFOSABI_FREEBSD, "FreeBSD" },
  714. { ELFOSABI_TRU64, "TRU64" },
  715. { ELFOSABI_MODESTO, "Modesto" },
  716. { ELFOSABI_OPENBSD, "OpenBSD" },
  717. { ELFOSABI_OPENVMS, "OpenVMS" },
  718. { ELFOSABI_NSK, "NSK" },
  719. { ELFOSABI_AROS, "AROS" },
  720. { ELFOSABI_FENIXOS, "FenixOS" }
  721. };
  722. /* Return ELFOSABI_XXX for an OSABI string, OSABI. */
  723. static int
  724. elf_osabi (const char *osabi)
  725. {
  726. unsigned int i;
  727. for (i = 0; i < ARRAY_SIZE (osabis); i++)
  728. if (strcasecmp (osabi, osabis[i].name) == 0)
  729. return osabis[i].osabi;
  730. error (_("Unknown OSABI: %s\n"), osabi);
  731. return -1;
  732. }
  733. /* Return EM_XXX for a machine string, MACH. */
  734. static int
  735. elf_machine (const char *mach)
  736. {
  737. if (strcasecmp (mach, "i386") == 0)
  738. return EM_386;
  739. if (strcasecmp (mach, "iamcu") == 0)
  740. return EM_IAMCU;
  741. if (strcasecmp (mach, "l1om") == 0)
  742. return EM_L1OM;
  743. if (strcasecmp (mach, "k1om") == 0)
  744. return EM_K1OM;
  745. if (strcasecmp (mach, "x86_64") == 0)
  746. return EM_X86_64;
  747. if (strcasecmp (mach, "x86-64") == 0)
  748. return EM_X86_64;
  749. if (strcasecmp (mach, "none") == 0)
  750. return EM_NONE;
  751. error (_("Unknown machine type: %s\n"), mach);
  752. return -1;
  753. }
  754. /* Return ET_XXX for a type string, TYPE. */
  755. static int
  756. elf_type (const char *type)
  757. {
  758. if (strcasecmp (type, "rel") == 0)
  759. return ET_REL;
  760. if (strcasecmp (type, "exec") == 0)
  761. return ET_EXEC;
  762. if (strcasecmp (type, "dyn") == 0)
  763. return ET_DYN;
  764. if (strcasecmp (type, "none") == 0)
  765. return ET_NONE;
  766. error (_("Unknown type: %s\n"), type);
  767. return -1;
  768. }
  769. enum command_line_switch
  770. {
  771. OPTION_INPUT_MACH = 150,
  772. OPTION_OUTPUT_MACH,
  773. OPTION_INPUT_TYPE,
  774. OPTION_OUTPUT_TYPE,
  775. OPTION_INPUT_OSABI,
  776. OPTION_OUTPUT_OSABI,
  777. OPTION_INPUT_ABIVERSION,
  778. OPTION_OUTPUT_ABIVERSION,
  779. #ifdef HAVE_MMAP
  780. OPTION_ENABLE_X86_FEATURE,
  781. OPTION_DISABLE_X86_FEATURE,
  782. #endif
  783. };
  784. static struct option options[] =
  785. {
  786. {"input-mach", required_argument, 0, OPTION_INPUT_MACH},
  787. {"output-mach", required_argument, 0, OPTION_OUTPUT_MACH},
  788. {"input-type", required_argument, 0, OPTION_INPUT_TYPE},
  789. {"output-type", required_argument, 0, OPTION_OUTPUT_TYPE},
  790. {"input-osabi", required_argument, 0, OPTION_INPUT_OSABI},
  791. {"output-osabi", required_argument, 0, OPTION_OUTPUT_OSABI},
  792. {"input-abiversion", required_argument, 0, OPTION_INPUT_ABIVERSION},
  793. {"output-abiversion", required_argument, 0, OPTION_OUTPUT_ABIVERSION},
  794. #ifdef HAVE_MMAP
  795. {"enable-x86-feature",
  796. required_argument, 0, OPTION_ENABLE_X86_FEATURE},
  797. {"disable-x86-feature",
  798. required_argument, 0, OPTION_DISABLE_X86_FEATURE},
  799. #endif
  800. {"version", no_argument, 0, 'v'},
  801. {"help", no_argument, 0, 'h'},
  802. {0, no_argument, 0, 0}
  803. };
  804. ATTRIBUTE_NORETURN static void
  805. usage (FILE *stream, int exit_status)
  806. {
  807. unsigned int i;
  808. char *osabi = concat (osabis[0].name, NULL);
  809. for (i = 1; i < ARRAY_SIZE (osabis); i++)
  810. osabi = reconcat (osabi, osabi, "|", osabis[i].name, NULL);
  811. fprintf (stream, _("Usage: %s <option(s)> elffile(s)\n"),
  812. program_name);
  813. fprintf (stream, _(" Update the ELF header of ELF files\n"));
  814. fprintf (stream, _(" The options are:\n"));
  815. fprintf (stream, _("\
  816. --input-mach [none|i386|iamcu|l1om|k1om|x86_64]\n\
  817. Set input machine type\n\
  818. --output-mach [none|i386|iamcu|l1om|k1om|x86_64]\n\
  819. Set output machine type\n\
  820. --input-type [none|rel|exec|dyn]\n\
  821. Set input file type\n\
  822. --output-type [none|rel|exec|dyn]\n\
  823. Set output file type\n\
  824. --input-osabi [%s]\n\
  825. Set input OSABI\n\
  826. --output-osabi [%s]\n\
  827. Set output OSABI\n\
  828. --input-abiversion [0-255] Set input ABIVERSION\n\
  829. --output-abiversion [0-255] Set output ABIVERSION\n"),
  830. osabi, osabi);
  831. #ifdef HAVE_MMAP
  832. fprintf (stream, _("\
  833. --enable-x86-feature [ibt|shstk|lam_u48|lam_u57]\n\
  834. Enable x86 feature\n\
  835. --disable-x86-feature [ibt|shstk|lam_u48|lam_u57]\n\
  836. Disable x86 feature\n"));
  837. #endif
  838. fprintf (stream, _("\
  839. -h --help Display this information\n\
  840. -v --version Display the version number of %s\n\
  841. "),
  842. program_name);
  843. if (REPORT_BUGS_TO[0] && exit_status == 0)
  844. fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
  845. free (osabi);
  846. exit (exit_status);
  847. }
  848. int
  849. main (int argc, char ** argv)
  850. {
  851. int c, status;
  852. char *end;
  853. #ifdef HAVE_LC_MESSAGES
  854. setlocale (LC_MESSAGES, "");
  855. #endif
  856. setlocale (LC_CTYPE, "");
  857. bindtextdomain (PACKAGE, LOCALEDIR);
  858. textdomain (PACKAGE);
  859. expandargv (&argc, &argv);
  860. while ((c = getopt_long (argc, argv, "hv",
  861. options, (int *) 0)) != EOF)
  862. {
  863. switch (c)
  864. {
  865. case OPTION_INPUT_MACH:
  866. input_elf_machine = elf_machine (optarg);
  867. if (input_elf_machine < 0)
  868. return 1;
  869. input_elf_class = elf_class (input_elf_machine);
  870. if (input_elf_class == ELF_CLASS_UNKNOWN)
  871. return 1;
  872. break;
  873. case OPTION_OUTPUT_MACH:
  874. output_elf_machine = elf_machine (optarg);
  875. if (output_elf_machine < 0)
  876. return 1;
  877. output_elf_class = elf_class (output_elf_machine);
  878. if (output_elf_class == ELF_CLASS_UNKNOWN)
  879. return 1;
  880. break;
  881. case OPTION_INPUT_TYPE:
  882. input_elf_type = elf_type (optarg);
  883. if (input_elf_type < 0)
  884. return 1;
  885. break;
  886. case OPTION_OUTPUT_TYPE:
  887. output_elf_type = elf_type (optarg);
  888. if (output_elf_type < 0)
  889. return 1;
  890. break;
  891. case OPTION_INPUT_OSABI:
  892. input_elf_osabi = elf_osabi (optarg);
  893. if (input_elf_osabi < 0)
  894. return 1;
  895. break;
  896. case OPTION_OUTPUT_OSABI:
  897. output_elf_osabi = elf_osabi (optarg);
  898. if (output_elf_osabi < 0)
  899. return 1;
  900. break;
  901. case OPTION_INPUT_ABIVERSION:
  902. input_elf_abiversion = strtoul (optarg, &end, 0);
  903. if (*end != '\0'
  904. || input_elf_abiversion < 0
  905. || input_elf_abiversion > 255)
  906. {
  907. error (_("Invalid ABIVERSION: %s\n"), optarg);
  908. return 1;
  909. }
  910. break;
  911. case OPTION_OUTPUT_ABIVERSION:
  912. output_elf_abiversion = strtoul (optarg, &end, 0);
  913. if (*end != '\0'
  914. || output_elf_abiversion < 0
  915. || output_elf_abiversion > 255)
  916. {
  917. error (_("Invalid ABIVERSION: %s\n"), optarg);
  918. return 1;
  919. }
  920. break;
  921. #ifdef HAVE_MMAP
  922. case OPTION_ENABLE_X86_FEATURE:
  923. if (elf_x86_feature (optarg, 1) < 0)
  924. return 1;
  925. break;
  926. case OPTION_DISABLE_X86_FEATURE:
  927. if (elf_x86_feature (optarg, 0) < 0)
  928. return 1;
  929. break;
  930. #endif
  931. case 'h':
  932. usage (stdout, 0);
  933. case 'v':
  934. print_version (program_name);
  935. break;
  936. default:
  937. usage (stderr, 1);
  938. }
  939. }
  940. if (optind == argc
  941. || (output_elf_machine == -1
  942. #ifdef HAVE_MMAP
  943. && ! enable_x86_features
  944. && ! disable_x86_features
  945. #endif
  946. && output_elf_type == -1
  947. && output_elf_osabi == -1
  948. && output_elf_abiversion == -1))
  949. usage (stderr, 1);
  950. status = 0;
  951. while (optind < argc)
  952. status |= process_file (argv[optind++]);
  953. return status;
  954. }