plugin.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /* Plugin support for BFD.
  2. Copyright (C) 2009-2015 Free Software Foundation, Inc.
  3. This file is part of BFD, the Binary File Descriptor library.
  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,
  15. MA 02110-1301, USA. */
  16. #include "sysdep.h"
  17. #include "bfd.h"
  18. #if BFD_SUPPORTS_PLUGINS
  19. #include <assert.h>
  20. #ifdef HAVE_DLFCN_H
  21. #include <dlfcn.h>
  22. #elif defined (HAVE_WINDOWS_H)
  23. #include <windows.h>
  24. #else
  25. #error Unknown how to handle dynamic-load-libraries.
  26. #endif
  27. #include <stdarg.h>
  28. #include "plugin-api.h"
  29. #include "plugin.h"
  30. #include "libbfd.h"
  31. #include "libiberty.h"
  32. #include <dirent.h>
  33. #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
  34. #define RTLD_NOW 0 /* Dummy value. */
  35. static void *
  36. dlopen (const char *file, int mode ATTRIBUTE_UNUSED)
  37. {
  38. return LoadLibrary (file);
  39. }
  40. static void *
  41. dlsym (void *handle, const char *name)
  42. {
  43. return GetProcAddress (handle, name);
  44. }
  45. static int ATTRIBUTE_UNUSED
  46. dlclose (void *handle)
  47. {
  48. FreeLibrary (handle);
  49. return 0;
  50. }
  51. static const char *
  52. dlerror (void)
  53. {
  54. return "Unable to load DLL.";
  55. }
  56. #endif /* !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H) */
  57. #define bfd_plugin_close_and_cleanup _bfd_generic_close_and_cleanup
  58. #define bfd_plugin_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
  59. #define bfd_plugin_new_section_hook _bfd_generic_new_section_hook
  60. #define bfd_plugin_get_section_contents _bfd_generic_get_section_contents
  61. #define bfd_plugin_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
  62. #define bfd_plugin_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
  63. #define bfd_plugin_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
  64. #define bfd_plugin_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
  65. #define bfd_plugin_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
  66. #define bfd_plugin_core_file_matches_executable_p generic_core_file_matches_executable_p
  67. #define bfd_plugin_bfd_is_local_label_name _bfd_nosymbols_bfd_is_local_label_name
  68. #define bfd_plugin_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
  69. #define bfd_plugin_get_lineno _bfd_nosymbols_get_lineno
  70. #define bfd_plugin_find_nearest_line _bfd_nosymbols_find_nearest_line
  71. #define bfd_plugin_find_line _bfd_nosymbols_find_line
  72. #define bfd_plugin_find_inliner_info _bfd_nosymbols_find_inliner_info
  73. #define bfd_plugin_get_symbol_version_string _bfd_nosymbols_get_symbol_version_string
  74. #define bfd_plugin_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
  75. #define bfd_plugin_read_minisymbols _bfd_generic_read_minisymbols
  76. #define bfd_plugin_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
  77. #define bfd_plugin_set_arch_mach bfd_default_set_arch_mach
  78. #define bfd_plugin_set_section_contents _bfd_generic_set_section_contents
  79. #define bfd_plugin_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
  80. #define bfd_plugin_bfd_relax_section bfd_generic_relax_section
  81. #define bfd_plugin_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
  82. #define bfd_plugin_bfd_link_add_symbols _bfd_generic_link_add_symbols
  83. #define bfd_plugin_bfd_link_just_syms _bfd_generic_link_just_syms
  84. #define bfd_plugin_bfd_final_link _bfd_generic_final_link
  85. #define bfd_plugin_bfd_link_split_section _bfd_generic_link_split_section
  86. #define bfd_plugin_bfd_gc_sections bfd_generic_gc_sections
  87. #define bfd_plugin_bfd_lookup_section_flags bfd_generic_lookup_section_flags
  88. #define bfd_plugin_bfd_merge_sections bfd_generic_merge_sections
  89. #define bfd_plugin_bfd_is_group_section bfd_generic_is_group_section
  90. #define bfd_plugin_bfd_discard_group bfd_generic_discard_group
  91. #define bfd_plugin_section_already_linked _bfd_generic_section_already_linked
  92. #define bfd_plugin_bfd_define_common_symbol bfd_generic_define_common_symbol
  93. #define bfd_plugin_bfd_copy_link_hash_symbol_type _bfd_generic_copy_link_hash_symbol_type
  94. static enum ld_plugin_status
  95. message (int level ATTRIBUTE_UNUSED,
  96. const char * format, ...)
  97. {
  98. va_list args;
  99. va_start (args, format);
  100. printf ("bfd plugin: ");
  101. vprintf (format, args);
  102. putchar ('\n');
  103. va_end (args);
  104. return LDPS_OK;
  105. }
  106. /* Register a claim-file handler. */
  107. static ld_plugin_claim_file_handler claim_file;
  108. static enum ld_plugin_status
  109. register_claim_file (ld_plugin_claim_file_handler handler)
  110. {
  111. claim_file = handler;
  112. return LDPS_OK;
  113. }
  114. static enum ld_plugin_status
  115. add_symbols (void * handle,
  116. int nsyms,
  117. const struct ld_plugin_symbol * syms)
  118. {
  119. bfd *abfd = handle;
  120. struct plugin_data_struct *plugin_data =
  121. bfd_alloc (abfd, sizeof (plugin_data_struct));
  122. plugin_data->nsyms = nsyms;
  123. plugin_data->syms = syms;
  124. if (nsyms != 0)
  125. abfd->flags |= HAS_SYMS;
  126. abfd->tdata.plugin_data = plugin_data;
  127. return LDPS_OK;
  128. }
  129. static const char *plugin_program_name;
  130. void
  131. bfd_plugin_set_program_name (const char *program_name)
  132. {
  133. plugin_program_name = program_name;
  134. }
  135. static int
  136. try_claim (bfd *abfd)
  137. {
  138. int claimed = 0;
  139. struct ld_plugin_input_file file;
  140. bfd *iobfd;
  141. file.name = abfd->filename;
  142. if (abfd->my_archive)
  143. {
  144. iobfd = abfd->my_archive;
  145. file.offset = abfd->origin;
  146. file.filesize = arelt_size (abfd);
  147. }
  148. else
  149. {
  150. iobfd = abfd;
  151. file.offset = 0;
  152. file.filesize = 0;
  153. }
  154. if (!iobfd->iostream && !bfd_open_file (iobfd))
  155. return 0;
  156. file.fd = fileno ((FILE *) iobfd->iostream);
  157. if (!abfd->my_archive)
  158. {
  159. struct stat stat_buf;
  160. if (fstat (file.fd, &stat_buf))
  161. return 0;
  162. file.filesize = stat_buf.st_size;
  163. }
  164. file.handle = abfd;
  165. off_t cur_offset = lseek(file.fd, 0, SEEK_CUR);
  166. claim_file (&file, &claimed);
  167. lseek(file.fd, cur_offset, SEEK_SET);
  168. if (!claimed)
  169. return 0;
  170. return 1;
  171. }
  172. static int
  173. try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p)
  174. {
  175. void *plugin_handle;
  176. int tv_size = 4;
  177. struct ld_plugin_tv tv[tv_size];
  178. int i;
  179. ld_plugin_onload onload;
  180. enum ld_plugin_status status;
  181. *has_plugin_p = 0;
  182. plugin_handle = dlopen (pname, RTLD_NOW);
  183. if (!plugin_handle)
  184. {
  185. (*_bfd_error_handler)("%s\n", dlerror ());
  186. return 0;
  187. }
  188. onload = dlsym (plugin_handle, "onload");
  189. if (!onload)
  190. goto err;
  191. i = 0;
  192. tv[i].tv_tag = LDPT_MESSAGE;
  193. tv[i].tv_u.tv_message = message;
  194. ++i;
  195. tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK;
  196. tv[i].tv_u.tv_register_claim_file = register_claim_file;
  197. ++i;
  198. tv[i].tv_tag = LDPT_ADD_SYMBOLS;
  199. tv[i].tv_u.tv_add_symbols = add_symbols;
  200. ++i;
  201. tv[i].tv_tag = LDPT_NULL;
  202. tv[i].tv_u.tv_val = 0;
  203. status = (*onload)(tv);
  204. if (status != LDPS_OK)
  205. goto err;
  206. *has_plugin_p = 1;
  207. abfd->plugin_format = bfd_plugin_no;
  208. if (!claim_file)
  209. goto err;
  210. if (!try_claim (abfd))
  211. goto err;
  212. abfd->plugin_format = bfd_plugin_yes;
  213. return 1;
  214. err:
  215. return 0;
  216. }
  217. /* There may be plugin libraries in lib/bfd-plugins. */
  218. static int has_plugin = -1;
  219. static const bfd_target *(*ld_plugin_object_p) (bfd *);
  220. static const char *plugin_name;
  221. void
  222. bfd_plugin_set_plugin (const char *p)
  223. {
  224. plugin_name = p;
  225. has_plugin = p != NULL;
  226. }
  227. /* Return TRUE if a plugin library is used. */
  228. bfd_boolean
  229. bfd_plugin_specified_p (void)
  230. {
  231. return has_plugin > 0;
  232. }
  233. extern const bfd_target plugin_vec;
  234. /* Return TRUE if TARGET is a pointer to plugin_vec. */
  235. bfd_boolean
  236. bfd_plugin_target_p (const bfd_target *target)
  237. {
  238. return target == &plugin_vec;
  239. }
  240. /* Register OBJECT_P to be used by bfd_plugin_object_p. */
  241. void
  242. register_ld_plugin_object_p (const bfd_target *(*object_p) (bfd *))
  243. {
  244. ld_plugin_object_p = object_p;
  245. }
  246. static int
  247. load_plugin (bfd *abfd)
  248. {
  249. char *plugin_dir;
  250. char *p;
  251. DIR *d;
  252. struct dirent *ent;
  253. int found = 0;
  254. if (!has_plugin)
  255. return found;
  256. if (plugin_name)
  257. return try_load_plugin (plugin_name, abfd, &has_plugin);
  258. if (plugin_program_name == NULL)
  259. return found;
  260. plugin_dir = concat (BINDIR, "/../lib/bfd-plugins", NULL);
  261. p = make_relative_prefix (plugin_program_name,
  262. BINDIR,
  263. plugin_dir);
  264. free (plugin_dir);
  265. plugin_dir = NULL;
  266. d = opendir (p);
  267. if (!d)
  268. goto out;
  269. while ((ent = readdir (d)))
  270. {
  271. char *full_name;
  272. struct stat s;
  273. int valid_plugin;
  274. full_name = concat (p, "/", ent->d_name, NULL);
  275. if (stat(full_name, &s) == 0 && S_ISREG (s.st_mode))
  276. found = try_load_plugin (full_name, abfd, &valid_plugin);
  277. if (has_plugin <= 0)
  278. has_plugin = valid_plugin;
  279. free (full_name);
  280. if (found)
  281. break;
  282. }
  283. out:
  284. free (p);
  285. if (d)
  286. closedir (d);
  287. return found;
  288. }
  289. static const bfd_target *
  290. bfd_plugin_object_p (bfd *abfd)
  291. {
  292. if (ld_plugin_object_p)
  293. return ld_plugin_object_p (abfd);
  294. if (abfd->plugin_format == bfd_plugin_uknown && !load_plugin (abfd))
  295. return NULL;
  296. return abfd->plugin_format == bfd_plugin_yes ? abfd->xvec : NULL;
  297. }
  298. /* Copy any private info we understand from the input bfd
  299. to the output bfd. */
  300. static bfd_boolean
  301. bfd_plugin_bfd_copy_private_bfd_data (bfd *ibfd ATTRIBUTE_UNUSED,
  302. bfd *obfd ATTRIBUTE_UNUSED)
  303. {
  304. BFD_ASSERT (0);
  305. return TRUE;
  306. }
  307. /* Copy any private info we understand from the input section
  308. to the output section. */
  309. static bfd_boolean
  310. bfd_plugin_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED,
  311. asection *isection ATTRIBUTE_UNUSED,
  312. bfd *obfd ATTRIBUTE_UNUSED,
  313. asection *osection ATTRIBUTE_UNUSED)
  314. {
  315. BFD_ASSERT (0);
  316. return TRUE;
  317. }
  318. /* Copy any private info we understand from the input symbol
  319. to the output symbol. */
  320. static bfd_boolean
  321. bfd_plugin_bfd_copy_private_symbol_data (bfd *ibfd ATTRIBUTE_UNUSED,
  322. asymbol *isymbol ATTRIBUTE_UNUSED,
  323. bfd *obfd ATTRIBUTE_UNUSED,
  324. asymbol *osymbol ATTRIBUTE_UNUSED)
  325. {
  326. BFD_ASSERT (0);
  327. return TRUE;
  328. }
  329. static bfd_boolean
  330. bfd_plugin_bfd_print_private_bfd_data (bfd *abfd ATTRIBUTE_UNUSED, PTR ptr ATTRIBUTE_UNUSED)
  331. {
  332. BFD_ASSERT (0);
  333. return TRUE;
  334. }
  335. static char *
  336. bfd_plugin_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
  337. {
  338. BFD_ASSERT (0);
  339. return NULL;
  340. }
  341. static int
  342. bfd_plugin_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
  343. {
  344. BFD_ASSERT (0);
  345. return 0;
  346. }
  347. static int
  348. bfd_plugin_core_file_pid (bfd *abfd ATTRIBUTE_UNUSED)
  349. {
  350. BFD_ASSERT (0);
  351. return 0;
  352. }
  353. static long
  354. bfd_plugin_get_symtab_upper_bound (bfd *abfd)
  355. {
  356. struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
  357. long nsyms = plugin_data->nsyms;
  358. BFD_ASSERT (nsyms >= 0);
  359. return ((nsyms + 1) * sizeof (asymbol *));
  360. }
  361. static flagword
  362. convert_flags (const struct ld_plugin_symbol *sym)
  363. {
  364. switch (sym->def)
  365. {
  366. case LDPK_DEF:
  367. case LDPK_COMMON:
  368. case LDPK_UNDEF:
  369. return BSF_GLOBAL;
  370. case LDPK_WEAKUNDEF:
  371. case LDPK_WEAKDEF:
  372. return BSF_GLOBAL | BSF_WEAK;
  373. default:
  374. BFD_ASSERT (0);
  375. return 0;
  376. }
  377. }
  378. static long
  379. bfd_plugin_canonicalize_symtab (bfd *abfd,
  380. asymbol **alocation)
  381. {
  382. struct plugin_data_struct *plugin_data = abfd->tdata.plugin_data;
  383. long nsyms = plugin_data->nsyms;
  384. const struct ld_plugin_symbol *syms = plugin_data->syms;
  385. static asection fake_section;
  386. static asection fake_common_section;
  387. int i;
  388. fake_section.name = ".text";
  389. fake_common_section.flags = SEC_IS_COMMON;
  390. for (i = 0; i < nsyms; i++)
  391. {
  392. asymbol *s = bfd_alloc (abfd, sizeof (asymbol));
  393. BFD_ASSERT (s);
  394. alocation[i] = s;
  395. s->the_bfd = abfd;
  396. s->name = syms[i].name;
  397. s->value = 0;
  398. s->flags = convert_flags (&syms[i]);
  399. switch (syms[i].def)
  400. {
  401. case LDPK_COMMON:
  402. s->section = &fake_common_section;
  403. break;
  404. case LDPK_UNDEF:
  405. case LDPK_WEAKUNDEF:
  406. s->section = bfd_und_section_ptr;
  407. break;
  408. case LDPK_DEF:
  409. case LDPK_WEAKDEF:
  410. s->section = &fake_section;
  411. break;
  412. default:
  413. BFD_ASSERT (0);
  414. }
  415. s->udata.p = (void *) &syms[i];
  416. }
  417. return nsyms;
  418. }
  419. static void
  420. bfd_plugin_print_symbol (bfd *abfd ATTRIBUTE_UNUSED,
  421. PTR afile ATTRIBUTE_UNUSED,
  422. asymbol *symbol ATTRIBUTE_UNUSED,
  423. bfd_print_symbol_type how ATTRIBUTE_UNUSED)
  424. {
  425. BFD_ASSERT (0);
  426. }
  427. static void
  428. bfd_plugin_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
  429. asymbol *symbol,
  430. symbol_info *ret)
  431. {
  432. bfd_symbol_info (symbol, ret);
  433. }
  434. /* Make an empty symbol. */
  435. static asymbol *
  436. bfd_plugin_make_empty_symbol (bfd *abfd)
  437. {
  438. asymbol *new_symbol = bfd_zalloc (abfd, sizeof (asymbol));
  439. if (new_symbol == NULL)
  440. return new_symbol;
  441. new_symbol->the_bfd = abfd;
  442. return new_symbol;
  443. }
  444. static int
  445. bfd_plugin_sizeof_headers (bfd *a ATTRIBUTE_UNUSED,
  446. struct bfd_link_info *info ATTRIBUTE_UNUSED)
  447. {
  448. BFD_ASSERT (0);
  449. return 0;
  450. }
  451. const bfd_target plugin_vec =
  452. {
  453. "plugin", /* Name. */
  454. bfd_target_unknown_flavour,
  455. BFD_ENDIAN_LITTLE, /* Target byte order. */
  456. BFD_ENDIAN_LITTLE, /* Target headers byte order. */
  457. (HAS_RELOC | EXEC_P | /* Object flags. */
  458. HAS_LINENO | HAS_DEBUG |
  459. HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
  460. (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
  461. | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags. */
  462. 0, /* symbol_leading_char. */
  463. '/', /* ar_pad_char. */
  464. 15, /* ar_max_namelen. */
  465. 0, /* match priority. */
  466. bfd_getl64, bfd_getl_signed_64, bfd_putl64,
  467. bfd_getl32, bfd_getl_signed_32, bfd_putl32,
  468. bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
  469. bfd_getl64, bfd_getl_signed_64, bfd_putl64,
  470. bfd_getl32, bfd_getl_signed_32, bfd_putl32,
  471. bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
  472. { /* bfd_check_format. */
  473. _bfd_dummy_target,
  474. bfd_plugin_object_p,
  475. bfd_generic_archive_p,
  476. _bfd_dummy_target
  477. },
  478. { /* bfd_set_format. */
  479. bfd_false,
  480. bfd_false,
  481. _bfd_generic_mkarchive,
  482. bfd_false,
  483. },
  484. { /* bfd_write_contents. */
  485. bfd_false,
  486. bfd_false,
  487. _bfd_write_archive_contents,
  488. bfd_false,
  489. },
  490. BFD_JUMP_TABLE_GENERIC (bfd_plugin),
  491. BFD_JUMP_TABLE_COPY (bfd_plugin),
  492. BFD_JUMP_TABLE_CORE (bfd_plugin),
  493. BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
  494. BFD_JUMP_TABLE_SYMBOLS (bfd_plugin),
  495. BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
  496. BFD_JUMP_TABLE_WRITE (bfd_plugin),
  497. BFD_JUMP_TABLE_LINK (bfd_plugin),
  498. BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
  499. NULL,
  500. NULL /* backend_data. */
  501. };
  502. #endif /* BFD_SUPPORTS_PLUGIN */