m68klinux.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 774 行 · 第 1/2 页
C
774 行
return true; } } /* Do the usual procedure for adding a symbol. */ if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, string, copy, collect, hashp)) return false; /* Insert a pointer to our table in the set vector. The dynamic linker requires this information */ if (insert) { asection *s; /* Here we do our special thing to add the pointer to the dynamic section in the SHARABLE_CONFLICTS set vector. */ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, ".linux-dynamic"); BFD_ASSERT (s != NULL); if (! (_bfd_generic_link_add_one_symbol (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS, BSF_GLOBAL | BSF_CONSTRUCTOR, s, 0, NULL, false, false, NULL))) return false; } return true;}/* We will crawl the hash table and come here for every global symbol. We will examine each entry and see if there are indications that we need to add a fixup. There are two possible cases - one is where you have duplicate definitions of PLT or GOT symbols - these will have already been caught and added as "builtin" fixups. If we find that the corresponding non PLT/GOT symbol is also present, we convert it to a regular fixup instead. This function is called via linux_link_hash_traverse. */static booleanlinux_tally_symbols (h, data) struct linux_link_hash_entry *h; PTR data;{ struct bfd_link_info *info = (struct bfd_link_info *) data; struct fixup *f, *f1; int is_plt; struct linux_link_hash_entry *h1, *h2; boolean exists; if (h->root.root.type == bfd_link_hash_undefined && strncmp (h->root.root.root.string, NEEDS_SHRLIB, sizeof NEEDS_SHRLIB - 1) == 0) { const char *name; char *p; char *alloc = NULL; name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1; p = strrchr (name, '_'); if (p != NULL) alloc = (char *) bfd_malloc (strlen (name) + 1); if (p == NULL || alloc == NULL) (*_bfd_error_handler) (_("Output file requires shared library `%s'\n"), name); else { strcpy (alloc, name); p = strrchr (alloc, '_'); *p++ = '\0'; (*_bfd_error_handler) (_("Output file requires shared library `%s.so.%s'\n"), alloc, p); free (alloc); } abort (); } /* If this symbol is not a PLT/GOT, we do not even need to look at it */ is_plt = IS_PLT_SYM (h->root.root.root.string); if (is_plt || IS_GOT_SYM (h->root.root.root.string)) { /* Look up this symbol twice. Once just as a regular lookup, and then again following all of the indirect links until we reach a real symbol. */ h1 = linux_link_hash_lookup (linux_hash_table (info), (h->root.root.root.string + sizeof PLT_REF_PREFIX - 1), false, false, true); /* h2 does not follow indirect symbols. */ h2 = linux_link_hash_lookup (linux_hash_table (info), (h->root.root.root.string + sizeof PLT_REF_PREFIX - 1), false, false, false); /* The real symbol must exist but if it is also an ABS symbol, there is no need to have a fixup. This is because they both came from the same library. If on the other hand, we had to use an indirect symbol to get to the real symbol, we add the fixup anyway, since there are cases where these symbols come from different shared libraries */ if (h1 != NULL && (((h1->root.root.type == bfd_link_hash_defined || h1->root.root.type == bfd_link_hash_defweak) && ! bfd_is_abs_section (h1->root.root.u.def.section)) || h2->root.root.type == bfd_link_hash_indirect)) { /* See if there is a "builtin" fixup already present involving this symbol. If so, convert it to a regular fixup. In the end, this relaxes some of the requirements about the order of performing fixups. */ exists = false; for (f1 = linux_hash_table (info)->fixup_list; f1 != NULL; f1 = f1->next) { if ((f1->h != h && f1->h != h1) || (! f1->builtin && ! f1->jump)) continue; if (f1->h == h1) exists = true; if (! exists && bfd_is_abs_section (h->root.root.u.def.section)) { f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0); f->jump = is_plt; } f1->h = h1; f1->jump = is_plt; f1->builtin = 0; exists = true; } if (! exists && bfd_is_abs_section (h->root.root.u.def.section)) { f = new_fixup (info, h1, h->root.root.u.def.value, 0); if (f == NULL) { /* FIXME: No way to return error. */ abort (); } f->jump = is_plt; } } /* Quick and dirty way of stripping these symbols from the symtab. */ if (bfd_is_abs_section (h->root.root.u.def.section)) h->root.written = true; } return true;}/* This is called to set the size of the .linux-dynamic section is. It is called by the Linux linker emulation before_allocation routine. We have finished reading all of the input files, and now we just scan the hash tables to find out how many additional fixups are required. */booleanbfd_m68klinux_size_dynamic_sections (output_bfd, info) bfd *output_bfd; struct bfd_link_info *info;{ struct fixup *f; asection *s; if (output_bfd->xvec != &MY(vec)) return true; /* First find the fixups... */ linux_link_hash_traverse (linux_hash_table (info), linux_tally_symbols, (PTR) info); /* If there are builtin fixups, leave room for a marker. This is used by the dynamic linker so that it knows that all that follow are builtin fixups instead of regular fixups. */ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next) { if (f->builtin) { ++linux_hash_table (info)->fixup_count; ++linux_hash_table (info)->local_builtins; break; } } if (linux_hash_table (info)->dynobj == NULL) { if (linux_hash_table (info)->fixup_count > 0) abort (); return true; } /* Allocate memory for our fixup table. We will fill it in later. */ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, ".linux-dynamic"); if (s != NULL) { s->_raw_size = 8 + linux_hash_table (info)->fixup_count * 8; s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size); if (s->contents == NULL) { bfd_set_error (bfd_error_no_memory); return false; } memset (s->contents, 0, (size_t) s->_raw_size); } return true;}/* We come here once we are ready to actually write the fixup table to the output file. Scan the fixup tables and so forth and generate the stuff we need. */static booleanlinux_finish_dynamic_link (output_bfd, info) bfd *output_bfd; struct bfd_link_info *info;{ asection *s, *os, *is; bfd_byte *fixup_table; struct linux_link_hash_entry *h; struct fixup *f; unsigned int new_addr; int section_offset; unsigned int fixups_written; if (linux_hash_table (info)->dynobj == NULL) return true; s = bfd_get_section_by_name (linux_hash_table (info)->dynobj, ".linux-dynamic"); BFD_ASSERT (s != NULL); os = s->output_section; fixups_written = 0;#ifdef LINUX_LINK_DEBUG printf ("Fixup table file offset: %x VMA: %x\n", os->filepos + s->output_offset, os->vma + s->output_offset);#endif fixup_table = s->contents; bfd_put_32 (output_bfd, linux_hash_table (info)->fixup_count, fixup_table); fixup_table += 4; /* Fill in fixup table. */ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next) { if (f->builtin) continue; if (f->h->root.root.type != bfd_link_hash_defined && f->h->root.root.type != bfd_link_hash_defweak) { (*_bfd_error_handler) (_("Symbol %s not defined for fixups\n"), f->h->root.root.root.string); continue; } is = f->h->root.root.u.def.section; section_offset = is->output_section->vma + is->output_offset; new_addr = f->h->root.root.u.def.value + section_offset;#ifdef LINUX_LINK_DEBUG printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string, new_addr, f->value);#endif if (f->jump) { bfd_put_32 (output_bfd, new_addr, fixup_table); fixup_table += 4; bfd_put_32 (output_bfd, f->value + 2, fixup_table); fixup_table += 4; } else { bfd_put_32 (output_bfd, new_addr, fixup_table); fixup_table += 4; bfd_put_32 (output_bfd, f->value, fixup_table); fixup_table += 4; } ++fixups_written; } if (linux_hash_table (info)->local_builtins != 0) { /* Special marker so we know to switch to the other type of fixup */ bfd_put_32 (output_bfd, 0, fixup_table); fixup_table += 4; bfd_put_32 (output_bfd, 0, fixup_table); fixup_table += 4; ++fixups_written; for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next) { if (! f->builtin) continue; if (f->h->root.root.type != bfd_link_hash_defined && f->h->root.root.type != bfd_link_hash_defweak) { (*_bfd_error_handler) (_("Symbol %s not defined for fixups\n"), f->h->root.root.root.string); continue; } is = f->h->root.root.u.def.section; section_offset = is->output_section->vma + is->output_offset; new_addr = f->h->root.root.u.def.value + section_offset;#ifdef LINUX_LINK_DEBUG printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string, new_addr, f->value);#endif bfd_put_32 (output_bfd, new_addr, fixup_table); fixup_table += 4; bfd_put_32 (output_bfd, f->value, fixup_table); fixup_table += 4; ++fixups_written; } } if (linux_hash_table (info)->fixup_count != fixups_written) { (*_bfd_error_handler) (_("Warning: fixup count mismatch\n")); while (linux_hash_table (info)->fixup_count > fixups_written) { bfd_put_32 (output_bfd, 0, fixup_table); fixup_table += 4; bfd_put_32 (output_bfd, 0, fixup_table); fixup_table += 4; ++fixups_written; } } h = linux_link_hash_lookup (linux_hash_table (info), "__BUILTIN_FIXUPS__", false, false, false); if (h != NULL && (h->root.root.type == bfd_link_hash_defined || h->root.root.type == bfd_link_hash_defweak)) { is = h->root.root.u.def.section; section_offset = is->output_section->vma + is->output_offset; new_addr = h->root.root.u.def.value + section_offset;#ifdef LINUX_LINK_DEBUG printf ("Builtin fixup table at %x\n", new_addr);#endif bfd_put_32 (output_bfd, new_addr, fixup_table); } else bfd_put_32 (output_bfd, 0, fixup_table); if (bfd_seek (output_bfd, os->filepos + s->output_offset, SEEK_SET) != 0) return false; if (bfd_write ((PTR) s->contents, 1, s->_raw_size, output_bfd) != s->_raw_size) return false; return true;}#define MY_bfd_link_hash_table_create linux_link_hash_table_create#define MY_add_one_symbol linux_add_one_symbol#define MY_finish_dynamic_link linux_finish_dynamic_link#define MY_zmagic_contiguous 1#include "aout-target.h"
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?