nlmconv.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,181 行 · 第 1/5 页
C
2,181 行
align = 1 << bss_sec->alignment_power; add = ((vma + align - 1) &~ (align - 1)) - vma; vma += add; if (! bfd_set_section_vma (outbfd, bss_sec, vma)) bfd_fatal (_("set .bss vma")); if (add != 0) { bfd_size_type data_size; data_size = bfd_get_section_size_before_reloc (data_sec); if (! bfd_set_section_size (outbfd, data_sec, data_size + add)) bfd_fatal (_("set .data size")); } } /* Adjust symbol information. */ inlead = bfd_get_symbol_leading_char (inbfd); outlead = bfd_get_symbol_leading_char (outbfd); gotstart = false; gotexit = false; gotcheck = false; newsymalloc = 10; newsyms = (asymbol **) xmalloc (newsymalloc * sizeof (asymbol *)); newsymcount = 0; endsym = NULL; for (i = 0; i < symcount; i++) { register asymbol *sym; sym = symbols[i]; /* Add or remove a leading underscore. */ if (inlead != outlead) { if (inlead != '\0') { if (bfd_asymbol_name (sym)[0] == inlead) { if (outlead == '\0') ++sym->name; else { char *new; new = xmalloc (strlen (bfd_asymbol_name (sym)) + 1); new[0] = outlead; strcpy (new + 1, bfd_asymbol_name (sym) + 1); sym->name = new; } } } else { char *new; new = xmalloc (strlen (bfd_asymbol_name (sym)) + 2); new[0] = outlead; strcpy (new + 1, bfd_asymbol_name (sym)); sym->name = new; } } /* NLM's have an uninitialized data section, but they do not have a common section in the Unix sense. Move all common symbols into the .bss section, and mark them as exported. */ if (bfd_is_com_section (bfd_get_section (sym))) { bfd_vma size; sym->section = bss_sec; size = sym->value; sym->value = bss_sec->_raw_size; bss_sec->_raw_size += size; align = 1 << bss_sec->alignment_power; bss_sec->_raw_size = (bss_sec->_raw_size + align - 1) &~ (align - 1); sym->flags |= BSF_EXPORT | BSF_GLOBAL; } else if (bfd_get_section (sym)->output_section != NULL) { /* Move the symbol into the output section. */ sym->value += bfd_get_section (sym)->output_offset; sym->section = bfd_get_section (sym)->output_section; /* This is no longer a section symbol. */ sym->flags &=~ BSF_SECTION_SYM; } /* Force _edata and _end to be defined. This would normally be done by the linker, but the manipulation of the common symbols will confuse it. */ if ((sym->flags & BSF_DEBUGGING) == 0 && bfd_asymbol_name (sym)[0] == '_' && bfd_is_und_section (bfd_get_section (sym))) { if (strcmp (bfd_asymbol_name (sym), "_edata") == 0) { sym->section = bss_sec; sym->value = 0; } if (strcmp (bfd_asymbol_name (sym), "_end") == 0) { sym->section = bss_sec; endsym = sym; }#ifdef NLMCONV_POWERPC /* For PowerPC NetWare, we define __GOT0. This is the start of the .got section. */ if (bfd_get_arch (inbfd) == bfd_arch_powerpc && strcmp (bfd_asymbol_name (sym), "__GOT0") == 0) { asection *got_sec; got_sec = bfd_get_section_by_name (inbfd, ".got"); assert (got_sec != (asection *) NULL); sym->value = got_sec->output_offset; sym->section = got_sec->output_section; }#endif } /* If this is a global symbol, check the export list. */ if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) != 0) { register struct string_list *l; int found_simple; /* Unfortunately, a symbol can appear multiple times on the export list, with and without prefixes. */ found_simple = 0; for (l = export_symbols; l != NULL; l = l->next) { if (strcmp (l->string, bfd_asymbol_name (sym)) == 0) found_simple = 1; else { char *zbase; zbase = strchr (l->string, '@'); if (zbase != NULL && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0) { /* We must add a symbol with this prefix. */ if (newsymcount >= newsymalloc) { newsymalloc += 10; newsyms = ((asymbol **) xrealloc ((PTR) newsyms, (newsymalloc * sizeof (asymbol *)))); } newsyms[newsymcount] = (asymbol *) xmalloc (sizeof (asymbol)); *newsyms[newsymcount] = *sym; newsyms[newsymcount]->name = l->string; ++newsymcount; } } } if (! found_simple) { /* The unmodified symbol is actually not exported at all. */ sym->flags &=~ (BSF_GLOBAL | BSF_EXPORT); sym->flags |= BSF_LOCAL; } } /* If it's an undefined symbol, see if it's on the import list. Change the prefix if necessary. */ if (bfd_is_und_section (bfd_get_section (sym))) { register struct string_list *l; for (l = import_symbols; l != NULL; l = l->next) { if (strcmp (l->string, bfd_asymbol_name (sym)) == 0) break; else { char *zbase; zbase = strchr (l->string, '@'); if (zbase != NULL && strcmp (zbase + 1, bfd_asymbol_name (sym)) == 0) { sym->name = l->string; break; } } } if (l == NULL) non_fatal (_("warning: symbol %s imported but not in import list"), bfd_asymbol_name (sym)); } /* See if it's one of the special named symbols. */ if ((sym->flags & BSF_DEBUGGING) == 0) { bfd_vma val; /* FIXME: If these symbols are not in the .text section, we add the .text section size to the value. This may not be correct for all targets. I'm not sure how this should really be handled. */ if (strcmp (bfd_asymbol_name (sym), start_procedure) == 0) { val = bfd_asymbol_value (sym); if (bfd_get_section (sym) == data_sec && text_sec != (asection *) NULL) val += bfd_section_size (outbfd, text_sec); if (! bfd_set_start_address (outbfd, val)) bfd_fatal (_("set start address")); gotstart = true; } if (strcmp (bfd_asymbol_name (sym), exit_procedure) == 0) { val = bfd_asymbol_value (sym); if (bfd_get_section (sym) == data_sec && text_sec != (asection *) NULL) val += bfd_section_size (outbfd, text_sec); nlm_fixed_header (outbfd)->exitProcedureOffset = val; gotexit = true; } if (check_procedure != NULL && strcmp (bfd_asymbol_name (sym), check_procedure) == 0) { val = bfd_asymbol_value (sym); if (bfd_get_section (sym) == data_sec && text_sec != (asection *) NULL) val += bfd_section_size (outbfd, text_sec); nlm_fixed_header (outbfd)->checkUnloadProcedureOffset = val; gotcheck = true; } } } if (endsym != NULL) { endsym->value = bfd_get_section_size_before_reloc (bss_sec); /* FIXME: If any relocs referring to _end use inplace addends, then I think they need to be updated. This is handled by i386_mangle_relocs. Is it needed for any other object formats? */ } if (newsymcount == 0) outsyms = symbols; else { outsyms = (asymbol **) xmalloc ((symcount + newsymcount + 1) * sizeof (asymbol *)); memcpy (outsyms, symbols, symcount * sizeof (asymbol *)); memcpy (outsyms + symcount, newsyms, newsymcount * sizeof (asymbol *)); outsyms[symcount + newsymcount] = NULL; } bfd_set_symtab (outbfd, outsyms, symcount + newsymcount); if (! gotstart) non_fatal (_("warning: START procedure %s not defined"), start_procedure); if (! gotexit) non_fatal (_("warning: EXIT procedure %s not defined"), exit_procedure); if (check_procedure != NULL && ! gotcheck) non_fatal (_("warning: CHECK procedure %s not defined"), check_procedure); /* Add additional sections required for the header information. */ if (custom_file != NULL) { custom_data = fopen (custom_file, "r"); if (custom_data == NULL || fstat (fileno (custom_data), &st) < 0) { fprintf (stderr, "%s:%s: %s\n", program_name, custom_file, strerror (errno)); custom_file = NULL; } else { custom_size = st.st_size; custom_section = bfd_make_section (outbfd, ".nlmcustom"); if (custom_section == NULL || ! bfd_set_section_size (outbfd, custom_section, custom_size) || ! bfd_set_section_flags (outbfd, custom_section, SEC_HAS_CONTENTS)) bfd_fatal (_("custom section")); } } if (help_file != NULL) { help_data = fopen (help_file, "r"); if (help_data == NULL || fstat (fileno (help_data), &st) < 0) { fprintf (stderr, "%s:%s: %s\n", program_name, help_file, strerror (errno)); help_file = NULL; } else { help_size = st.st_size; help_section = bfd_make_section (outbfd, ".nlmhelp"); if (help_section == NULL || ! bfd_set_section_size (outbfd, help_section, help_size) || ! bfd_set_section_flags (outbfd, help_section, SEC_HAS_CONTENTS)) bfd_fatal (_("help section")); strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); } } if (message_file != NULL) { message_data = fopen (message_file, "r"); if (message_data == NULL || fstat (fileno (message_data), &st) < 0) { fprintf (stderr, "%s:%s: %s\n", program_name, message_file, strerror (errno)); message_file = NULL; } else { message_size = st.st_size; message_section = bfd_make_section (outbfd, ".nlmmessages"); if (message_section == NULL || ! bfd_set_section_size (outbfd, message_section, message_size) || ! bfd_set_section_flags (outbfd, message_section, SEC_HAS_CONTENTS)) bfd_fatal (_("message section")); strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); } } if (modules != NULL) { struct string_list *l; module_size = 0; for (l = modules; l != NULL; l = l->next) module_size += strlen (l->string) + 1; module_section = bfd_make_section (outbfd, ".nlmmodules"); if (module_section == NULL || ! bfd_set_section_size (outbfd, module_section, module_size) || ! bfd_set_section_flags (outbfd, module_section, SEC_HAS_CONTENTS)) bfd_fatal (_("module section")); } if (rpc_file != NULL) { rpc_data = fopen (rpc_file, "r"); if (rpc_data == NULL || fstat (fileno (rpc_data), &st) < 0) { fprintf (stderr, "%s:%s: %s\n", program_name, rpc_file, strerror (errno)); rpc_file = NULL; } else { rpc_size = st.st_size; rpc_section = bfd_make_section (outbfd, ".nlmrpc"); if (rpc_section == NULL || ! bfd_set_section_size (outbfd, rpc_section, rpc_size) || ! bfd_set_section_flags (outbfd, rpc_section, SEC_HAS_CONTENTS)) bfd_fatal (_("rpc section")); strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); } } if (sharelib_file != NULL) { sharedbfd = bfd_openr (sharelib_file, output_format); if (sharedbfd == NULL || ! bfd_check_format (sharedbfd, bfd_object)) { fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file, bfd_errmsg (bfd_get_error ())); sharelib_file = NULL; } else { sharedhdr = *nlm_fixed_header (sharedbfd); bfd_close (sharedbfd); shared_data = fopen (sharelib_file, "r"); if (shared_data == NULL || (fstat (fileno (shared_data), &st) < 0)) { fprintf (stderr, "%s:%s: %s\n", program_name, sharelib_file, strerror (errno)); sharelib_file = NULL; } else { /* If we were clever, we could just copy out the sections of the shared library which we actually need. However, we would have to figure out the sizes of the external and public information, and that can not be done without reading through them. */ if (sharedhdr.uninitializedDataSize > 0) { /* There is no place to record this information. */ non_fatal (_("%s: warning: shared libraries can not have uninitialized data"), sharelib_file); } shared_offset = st.st_size; if (shared_offset > (size_t) sharedhdr.codeImageOffset) shared_offset = sharedhdr.codeImageOffset; if (shared_offset > (size_t) sharedhdr.dataImageOffset) shared_offset = sharedhdr.dataImageOffset; if (shared_offset > (size_t) sharedhdr.relocationFixupOffset) shared_offset = sharedhdr.relocationFixupOffset; if (shared_offset > (size_t) sharedhdr.externalReferencesOffset) shared_offset = sharedhdr.externalReferencesOffset; if (shared_offset > (size_t) sharedhdr.publicsOffset) shared_offset = sharedhdr.publicsOffset; shared_size = st.st_size - shared_offset; shared_section = bfd_make_section (outbfd, ".nlmshared"); if (shared_section == NULL || ! bfd_set_section_size (outbfd, shared_section, shared_size) || ! bfd_set_section_flags (outbfd, shared_section, SEC_HAS_CONTENTS)) bfd_fatal (_("shared section")); strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); } } } /* Check whether a version was given. */ if (strncmp (version_hdr->stamp, "VeRsIoN#", 8) != 0) non_fatal (_("warning: No version number given")); /* At least for now, always create an extended header, because that is what NLMLINK does. */ strncpy (nlm_extended_header (outbfd)->stamp, "MeSsAgEs", 8); strncpy (nlm_cygnus_ext_header (outbfd)->stamp, "CyGnUsEx", 8);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?