📄 sunos.em
字号:
} else { dircopy = (char *) xmalloc (s - path + 1); memcpy (dircopy, path, s - path); dircopy[s - path] = '\0'; dir = dircopy; } if (gld${EMULATION_NAME}_try_needed (dir, name)) return true; if (dircopy != NULL) free (dircopy); if (s == NULL) break; path = s + 1; } return false; }/* This function is called for each possible directory for a needed dynamic object. */static booleangld${EMULATION_NAME}_try_needed (dir, name) const char *dir; const char *name;{ char *file; char *alc; boolean ignore; bfd *abfd; file = gld${EMULATION_NAME}_search_dir (dir, name, &ignore); if (file == NULL) return false; alc = (char *) xmalloc (strlen (dir) + strlen (file) + 2); sprintf (alc, "%s/%s", dir, file); free (file); abfd = bfd_openr (alc, bfd_get_target (output_bfd)); if (abfd == NULL) return false; if (! bfd_check_format (abfd, bfd_object)) { (void) bfd_close (abfd); return false; } if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) { (void) bfd_close (abfd); return false; } /* We've found the needed dynamic object. */ /* Add this file into the symbol table. */ if (! bfd_link_add_symbols (abfd, &link_info)) einfo ("%F%B: could not read symbols: %E\n", abfd); return true;}/* See if we have already included a needed object in the link. This does not have to be precise, as it does no harm to include a dynamic object more than once. */static voidgld${EMULATION_NAME}_check_needed (s) lang_input_statement_type *s;{ if (s->filename == NULL) return; if (strncmp (global_needed->name, "-l", 2) != 0) { if (strcmp (s->filename, global_needed->name) == 0) global_found = true; } else { const char *sname, *lname; const char *sdot, *ldot; int lmaj, lmin, smaj, smin; lname = global_needed->name + 2; sname = strrchr (s->filename, '/'); if (sname == NULL) sname = s->filename; else ++sname; if (strncmp (sname, "lib", 3) != 0) return; sname += 3; ldot = strchr (lname, '.'); if (ldot == NULL) ldot = lname + strlen (lname); sdot = strstr (sname, ".so."); if (sdot == NULL) return; if (sdot - sname != ldot - lname || strncmp (lname, sname, sdot - sname) != 0) return; lmaj = lmin = -1; sscanf (ldot, ".%d.%d", &lmaj, &lmin); smaj = smin = -1; sscanf (sdot, ".so.%d.%d", &smaj, &smin); if ((smaj != lmaj && smaj != -1 && lmaj != -1) || (smin != lmin && smin != -1 && lmin != -1)) return; global_found = true; }}/* We need to use static variables to pass information around the call to lang_for_each_statement. Ick. */static const char *find_assign;static boolean found_assign;/* We need to use static variables to pass information around the call to lang_for_each_input_file. Ick. */static bfd_size_type need_size;static bfd_size_type need_entries;static bfd_byte *need_contents;static bfd_byte *need_pinfo;static bfd_byte *need_pnames;/* The size of one entry in the .need section, not including the file name. */#define NEED_ENTRY_SIZE (16)/* This is called after the sections have been attached to output sections, but before any sizes or addresses have been set. */static voidgld${EMULATION_NAME}_before_allocation (){ struct bfd_link_hash_entry *hdyn = NULL; asection *sneed; asection *srules; asection *sdyn; /* The SunOS native linker creates a shared library whenever there are any undefined symbols in a link, unless -e is used. This is pretty weird, but we are compatible. */ if (! link_info.shared && ! link_info.relocateable && ! entry_from_cmdline) { struct bfd_link_hash_entry *h; for (h = link_info.hash->undefs; h != NULL; h = h->next) { if (h->type == bfd_link_hash_undefined && h->u.undef.abfd != NULL && (h->u.undef.abfd->flags & DYNAMIC) == 0 && strcmp (h->root.string, "__DYNAMIC") != 0 && strcmp (h->root.string, "__GLOBAL_OFFSET_TABLE_") != 0) { find_assign = h->root.string; found_assign = false; lang_for_each_statement (gld${EMULATION_NAME}_find_assignment); if (! found_assign) { link_info.shared = true; break; } } } } if (link_info.shared) { lang_output_section_statement_type *os; /* Set the .text section to start at 0x20, not 0x2020. FIXME: This is too magical. */ os = lang_output_section_statement_lookup (".text"); if (os->addr_tree == NULL) os->addr_tree = exp_intop (0x20); } /* We need to create a __DYNAMIC symbol. We don't do this in the linker script because we want to set the value to the start of the dynamic section if there is one, or to zero if there isn't one. We need to create the symbol before calling size_dynamic_sections, although we can't set the value until afterward. */ if (! link_info.relocateable) { hdyn = bfd_link_hash_lookup (link_info.hash, "__DYNAMIC", true, false, false); if (hdyn == NULL) einfo ("%P%F: bfd_link_hash_lookup: %E\n"); if (! bfd_sunos_record_link_assignment (output_bfd, &link_info, "__DYNAMIC")) einfo ("%P%F: failed to record assignment to __DYNAMIC: %E\n"); } /* If we are going to make any variable assignments, we need to let the backend linker know about them in case the variables are referred to by dynamic objects. */ lang_for_each_statement (gld${EMULATION_NAME}_find_assignment); /* Let the backend linker work out the sizes of any sections required by dynamic linking. */ if (! bfd_sunos_size_dynamic_sections (output_bfd, &link_info, &sdyn, &sneed, &srules)) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); if (sneed != NULL) { /* Set up the .need section. See the description of the ld_need field in include/aout/sun4.h. */ need_entries = 0; need_size = 0; lang_for_each_input_file (gld${EMULATION_NAME}_count_need); /* We should only have a .need section if we have at least one dynamic object. */ ASSERT (need_entries != 0); sneed->_raw_size = need_size; sneed->contents = (bfd_byte *) xmalloc (need_size); need_contents = sneed->contents; need_pinfo = sneed->contents; need_pnames = sneed->contents + need_entries * 16; lang_for_each_input_file (gld${EMULATION_NAME}_set_need); ASSERT ((bfd_size_type) (need_pnames - sneed->contents) == need_size); } if (srules != NULL) { /* Set up the .rules section. This is just a PATH like string of the -L arguments given on the command line. We permit the user to specify the directories using the -rpath command line option. */ if (command_line.rpath) { srules->_raw_size = strlen (command_line.rpath); srules->contents = (bfd_byte *) command_line.rpath; } else { unsigned int size; search_dirs_type *search; size = 0; for (search = search_head; search != NULL; search = search->next) if (search->cmdline) size += strlen (search->name) + 1; srules->_raw_size = size; if (size > 0) { char *p; srules->contents = (bfd_byte *) xmalloc (size); p = (char *) srules->contents; *p = '\0'; for (search = search_head; search != NULL; search = search->next) { if (search->cmdline) { if (p != (char *) srules->contents) *p++ = ':'; strcpy (p, search->name); p += strlen (p); } } } } } /* We must assign a value to __DYNAMIC. It should be zero if we are not doing a dynamic link, or the start of the .dynamic section if we are doing one. */ if (! link_info.relocateable) { hdyn->type = bfd_link_hash_defined; hdyn->u.def.value = 0; if (sdyn != NULL) hdyn->u.def.section = sdyn; else hdyn->u.def.section = bfd_abs_section_ptr; }}/* This is called by the before_allocation routine via lang_for_each_statement. It does one of two things: if the variable find_assign is set, it sets found_assign if it finds an assignment to that variable; otherwise it tells the backend linker about all assignment statements, in case they are assignments to symbols which are referred to by dynamic objects. */static voidgld${EMULATION_NAME}_find_assignment (s) lang_statement_union_type *s;{ if (s->header.type == lang_assignment_statement_enum && (find_assign == NULL || ! found_assign)) gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);}/* Look through an expression for an assignment statement. */static voidgld${EMULATION_NAME}_find_exp_assignment (exp) etree_type *exp;{ switch (exp->type.node_class) { case etree_assign: if (find_assign != NULL) { if (strcmp (find_assign, exp->assign.dst) == 0) found_assign = true; return; } if (strcmp (exp->assign.dst, ".") != 0) { if (! bfd_sunos_record_link_assignment (output_bfd, &link_info, exp->assign.dst)) einfo ("%P%F: failed to record assignment to %s: %E\n", exp->assign.dst); } gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src); break; case etree_binary: gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs); gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs); break; case etree_trinary: gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond); gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs); gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs); break; case etree_unary: gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child); break; default: break; }}/* Work out the size of the .need section, and the number of entries. The backend will set the ld_need field of the dynamic linking information to point to the .need section. See include/aout/sun4.h for more information. */static voidgld${EMULATION_NAME}_count_need (inp) lang_input_statement_type *inp;{ if (inp->the_bfd != NULL && (inp->the_bfd->flags & DYNAMIC) != 0) { ++need_entries; need_size += NEED_ENTRY_SIZE; if (! inp->is_archive) need_size += strlen (inp->filename) + 1; else { ASSERT (inp->local_sym_name[0] == '-' && inp->local_sym_name[1] == 'l'); need_size += strlen (inp->local_sym_name + 2) + 1; } }}/* Fill in the contents of the .need section. */static voidgld${EMULATION_NAME}_set_need (inp) lang_input_statement_type *inp;{ if (inp->the_bfd != NULL && (inp->the_bfd->flags & DYNAMIC) != 0) { bfd_size_type c; /* To really fill in the .need section contents, we need to know the final file position of the section, but we don't. Instead, we use offsets, and rely on the BFD backend to finish the section up correctly. FIXME: Talk about lack of referential locality. */ bfd_put_32 (output_bfd, need_pnames - need_contents, need_pinfo); if (! inp->is_archive) { bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 4); bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 8); bfd_put_16 (output_bfd, (bfd_vma) 0, need_pinfo + 10); strcpy (need_pnames, inp->filename); } else { char *verstr; int maj, min; bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, need_pinfo + 4); maj = 0; min = 0; verstr = strstr (inp->filename, ".so."); if (verstr != NULL) sscanf (verstr, ".so.%d.%d", &maj, &min); bfd_put_16 (output_bfd, (bfd_vma) maj, need_pinfo + 8); bfd_put_16 (output_bfd, (bfd_vma) min, need_pinfo + 10); strcpy (need_pnames, inp->local_sym_name + 2); } c = (need_pinfo - need_contents) / NEED_ENTRY_SIZE; if (c + 1 >= need_entries) bfd_put_32 (output_bfd, (bfd_vma) 0, need_pinfo + 12); else bfd_put_32 (output_bfd, (bfd_vma) (c + 1) * NEED_ENTRY_SIZE, need_pinfo + 12); need_pinfo += NEED_ENTRY_SIZE; need_pnames += strlen (need_pnames) + 1; }}static char *gld${EMULATION_NAME}_get_script(isfile) int *isfile;EOFif test -n "$COMPILE_IN"then# Scripts compiled in.# sed commands to quote an ld script as a C string.sc="-f stringify.sed"cat >>e${EMULATION_NAME}.c <<EOF{ *isfile = 0; if (link_info.relocateable == true && config.build_constructors == true) returnEOFsed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.cecho ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.csed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.cecho ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.csed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.cecho ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.csed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.cecho ' ; else return' >> e${EMULATION_NAME}.csed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.cecho '; }' >> e${EMULATION_NAME}.celse# Scripts read from the filesystem.cat >>e${EMULATION_NAME}.c <<EOF{ *isfile = 1; if (link_info.relocateable == true && config.build_constructors == true) return "ldscripts/${EMULATION_NAME}.xu"; else if (link_info.relocateable == true) return "ldscripts/${EMULATION_NAME}.xr"; else if (!config.text_read_only) return "ldscripts/${EMULATION_NAME}.xbn"; else if (!config.magic_demand_paged) return "ldscripts/${EMULATION_NAME}.xn"; else return "ldscripts/${EMULATION_NAME}.x";}EOFficat >>e${EMULATION_NAME}.c <<EOFstruct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = { gld${EMULATION_NAME}_before_parse, syslib_default, hll_default, after_parse_default, gld${EMULATION_NAME}_after_open, after_allocation_default, set_output_arch_default, ldemul_default_target, gld${EMULATION_NAME}_before_allocation, gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", NULL, /* finish */ gld${EMULATION_NAME}_create_output_section_statements, NULL, /* open dynamic archive */ NULL, /* place orphan */ gld${EMULATION_NAME}_set_symbols, NULL, /* parse args */ NULL, /* unrecognized file */ NULL, /* list options */ NULL, /* recognized file */ NULL /* find_potential_libraries */};EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -