📄 collect2.c
字号:
write_list_with_asm (stream, prefix, list) FILE *stream; char *prefix; struct id *list;{ while (list) { fprintf (stream, "%sx%d asm (\"%s\");\n", prefix, list->sequence, list->name); list = list->next; }}/* Write the constructor/destructor tables. */static voidwrite_c_file (stream, name) FILE *stream; char *name;{ /* Write the tables as C code */ fprintf (stream, "typedef void entry_pt();\n\n"); write_list_with_asm (stream, "extern entry_pt ", constructors.first); fprintf (stream, "\nentry_pt * __CTOR_LIST__[] = {\n"); fprintf (stream, "\t(entry_pt *) %d,\n", constructors.number); write_list (stream, "\t", constructors.first); fprintf (stream, "\t0\n};\n\n"); write_list_with_asm (stream, "extern entry_pt ", destructors.first); fprintf (stream, "\nentry_pt * __DTOR_LIST__[] = {\n"); fprintf (stream, "\t(entry_pt *) %d,\n", destructors.number); write_list (stream, "\t", destructors.first); fprintf (stream, "\t0\n};\n\n"); fprintf (stream, "extern entry_pt __main;\n"); fprintf (stream, "entry_pt *__main_reference = __main;\n\n");}#ifdef OBJECT_FORMAT_NONE/* Generic version to scan the name list of the loaded program for the symbols g++ uses for static constructors and destructors. The constructor table begins at __CTOR_LIST__ and contains a count of the number of pointers (or -1 if the constructors are built in a separate section by the linker), followed by the pointers to the constructor functions, terminated with a null pointer. The destructor table has the same format, and begins at __DTOR_LIST__. */static voidscan_prog_file (prog_name, which_pass) char *prog_name; enum pass which_pass;{ void (*int_handler) (); void (*quit_handler) (); char *nm_argv[4]; int pid; int argc = 0; int pipe_fd[2]; char *p, buf[1024]; FILE *inf; if (which_pass != PASS_FIRST) return; nm_argv[argc++] = "nm"; if (NM_FLAGS[0] != '\0') nm_argv[argc++] = NM_FLAGS; nm_argv[argc++] = prog_name; nm_argv[argc++] = (char *)0; if (pipe (pipe_fd) < 0) fatal_perror ("pipe"); inf = fdopen (pipe_fd[0], "r"); if (inf == (FILE *)0) fatal_perror ("fdopen"); /* Trace if needed. */ if (vflag) { char **p_argv; char *str; fprintf (stderr, "%s", nm_file_name); for (p_argv = &nm_argv[1]; (str = *p_argv) != (char *)0; p_argv++) fprintf (stderr, " %s", str); fprintf (stderr, "\n"); } fflush (stdout); fflush (stderr); /* Spawn child nm on pipe */ pid = vfork (); if (pid == -1) fatal_perror ("vfork"); if (pid == 0) /* child context */ { /* setup stdout */ if (dup2 (pipe_fd[1], 1) < 0) fatal_perror ("dup2 (%d, 1)", pipe_fd[1]); if (close (pipe_fd[0]) < 0) fatal_perror ("close (%d)", pipe_fd[0]); if (close (pipe_fd[1]) < 0) fatal_perror ("close (%d)", pipe_fd[1]); execv (nm_file_name, nm_argv); fatal_perror ("executing %s", nm_file_name); } /* Parent context from here on. */ int_handler = (void (*) ())signal (SIGINT, SIG_IGN); quit_handler = (void (*) ())signal (SIGQUIT, SIG_IGN); if (close (pipe_fd[1]) < 0) fatal_perror ("close (%d)", pipe_fd[1]); if (debug) fprintf (stderr, "\nnm output with constructors/destructors.\n"); /* Read each line of nm output. */ while (fgets (buf, sizeof buf, inf) != (char *)0) { int ch, ch2; char *name, *end; /* If it contains a constructor or destructor name, add the name to the appropriate list. */ for (p = buf; (ch = *p) != '\0' && ch != '\n' && ch != '_'; p++) ; if (ch == '\0' || ch == '\n') continue; name = p; /* Find the end of the symbol name. Don't include `|', because Encore nm can tack that on the end. */ for (end = p; (ch2 = *end) != '\0' && !isspace (ch2) && ch2 != '|'; end++) continue; *end = '\0'; switch (is_ctor_dtor (name)) { case 1: add_to_list (&constructors, name); break; case 2: add_to_list (&destructors, name); break; default: /* not a constructor or destructor */ continue; } if (debug) fprintf (stderr, "\t%s\n", buf); } if (debug) fprintf (stderr, "\n"); if (fclose (inf) != 0) fatal_perror ("fclose of pipe"); do_wait (nm_file_name); signal (SIGINT, int_handler); signal (SIGQUIT, quit_handler);}#endif /* OBJECT_FORMAT_NONE *//* * COFF specific stuff. */#ifdef OBJECT_FORMAT_COFF#if defined(EXTENDED_COFF)# define GCC_SYMBOLS(X) (SYMHEADER(X).isymMax + SYMHEADER(X).iextMax)# define GCC_SYMENT SYMR# define GCC_OK_SYMBOL(X) ((X).st == stProc && (X).sc == scText)# define GCC_SYMINC(X) (1)# define GCC_SYMZERO(X) (SYMHEADER(X).isymMax)# define GCC_CHECK_HDR(X) (PSYMTAB(X) != 0)#else# define GCC_SYMBOLS(X) (HEADER(ldptr).f_nsyms)# define GCC_SYMENT SYMENT# define GCC_OK_SYMBOL(X) \ (((X).n_sclass == C_EXT) && \ (((X).n_type & N_TMASK) == (DT_NON << N_BTSHFT) || \ ((X).n_type & N_TMASK) == (DT_FCN << N_BTSHFT)))# define GCC_SYMINC(X) ((X).n_numaux+1)# define GCC_SYMZERO(X) 0# define GCC_CHECK_HDR(X) (1)#endifextern char *ldgetname ();/* COFF version to scan the name list of the loaded program for the symbols g++ uses for static constructors and destructors. The constructor table begins at __CTOR_LIST__ and contains a count of the number of pointers (or -1 if the constructors are built in a separate section by the linker), followed by the pointers to the constructor functions, terminated with a null pointer. The destructor table has the same format, and begins at __DTOR_LIST__. */static voidscan_prog_file (prog_name, which_pass) char *prog_name; enum pass which_pass;{ LDFILE *ldptr = NULL; int sym_index, sym_count; if (which_pass != PASS_FIRST) return; if ((ldptr = ldopen (prog_name, ldptr)) == NULL) fatal ("%s: can't open as COFF file", prog_name); if (!MY_ISCOFF (HEADER (ldptr).f_magic)) fatal ("%s: not a COFF file", prog_name); if (GCC_CHECK_HDR (ldptr)) { sym_count = GCC_SYMBOLS (ldptr); sym_index = GCC_SYMZERO (ldptr); while (sym_index < sym_count) { GCC_SYMENT symbol; if (ldtbread (ldptr, sym_index, &symbol) <= 0) break; sym_index += GCC_SYMINC (symbol); if (GCC_OK_SYMBOL (symbol)) { char *name; if ((name = ldgetname (ldptr, &symbol)) == NULL) continue; /* should never happen */#ifdef _AIX /* All AIX function names begin with a dot. */ if (*name++ != '.') continue;#endif switch (is_ctor_dtor (name)) { case 1: add_to_list (&constructors, name); break; case 2: add_to_list (&destructors, name); break; default: /* not a constructor or destructor */ continue; }#if !defined(EXTENDED_COFF) if (debug) fprintf (stderr, "\tsec=%d class=%d type=%s%o %s\n", symbol.n_scnum, symbol.n_sclass, (symbol.n_type ? "0" : ""), symbol.n_type, name);#else if (debug) fprintf (stderr, "\tiss = %5d, value = %5d, index = %5d, name = %s\n", symbol.iss, symbol.value, symbol.index, name);#endif } } } (void) ldclose(ldptr);}#endif /* OBJECT_FORMAT_COFF *//* * OSF/rose specific stuff. */#ifdef OBJECT_FORMAT_ROSE/* Union of the various load commands */typedef union load_union{ ldc_header_t hdr; /* common header */ load_cmd_map_command_t map; /* map indexing other load cmds */ interpreter_command_t iprtr; /* interpreter pathname */ strings_command_t str; /* load commands strings section */ region_command_t region; /* region load command */ reloc_command_t reloc; /* relocation section */ package_command_t pkg; /* package load command */ symbols_command_t sym; /* symbol sections */ entry_command_t ent; /* program start section */ gen_info_command_t info; /* object information */ func_table_command_t func; /* function constructors/destructors */} load_union_t;/* Structure to point to load command and data section in memory. */typedef struct load_all{ load_union_t *load; /* load command */ char *section; /* pointer to section */} load_all_t;/* Structure to contain information about a file mapped into memory. */struct file_info{ char *start; /* start of map */ char *name; /* filename */ long size; /* size of the file */ long rounded_size; /* size rounded to page boundary */ int fd; /* file descriptor */ int rw; /* != 0 if opened read/write */ int use_mmap; /* != 0 if mmap'ed */};extern int decode_mach_o_hdr ();extern int encode_mach_o_hdr ();static void bad_header ();static void print_header ();static void print_load_command ();static void add_func_table ();static struct file_info *read_file ();static void end_file ();/* OSF/rose specific version to scan the name list of the loaded program for the symbols g++ uses for static constructors and destructors. The constructor table begins at __CTOR_LIST__ and contains a count of the number of pointers (or -1 if the constructors are built in a separate section by the linker), followed by the pointers to the constructor functions, terminated with a null pointer. The destructor table has the same format, and begins at __DTOR_LIST__. */static voidscan_prog_file (prog_name, which_pass) char *prog_name; enum pass which_pass;{ char *obj; mo_header_t hdr; load_all_t *load_array; load_all_t *load_end; load_all_t *load_cmd; int symbol_load_cmds; off_t offset; int i; int num_syms; int status; char *str_sect; struct file_info *obj_file; int prog_fd; mo_lcid_t cmd_strings = -1; symbol_info_t *main_sym = 0; int rw = (which_pass != PASS_FIRST); prog_fd = open (prog_name, (rw) ? O_RDWR : O_RDONLY); if (prog_fd < 0) fatal_perror ("can't read %s", prog_name); obj_file = read_file (prog_name, prog_fd, rw); obj = obj_file->start; status = decode_mach_o_hdr (obj, MO_SIZEOF_RAW_HDR, MOH_HEADER_VERSION, &hdr); if (status != MO_HDR_CONV_SUCCESS) bad_header (status); /* Do some basic sanity checks. Note we explicitly use the big endian magic number, since the hardware will automatically swap bytes for us on loading little endian integers. */#ifndef CROSS_COMPILE if (hdr.moh_magic != MOH_MAGIC_MSB || hdr.moh_header_version != MOH_HEADER_VERSION || hdr.moh_byte_order != OUR_BYTE_ORDER || hdr.moh_data_rep_id != OUR_DATA_REP_ID || hdr.moh_cpu_type != OUR_CPU_TYPE || hdr.moh_cpu_subtype != OUR_CPU_SUBTYPE || hdr.moh_vendor_type != OUR_VENDOR_TYPE) { fatal ("incompatibilities between object file & expected values"); }#endif if (debug) print_header (&hdr); offset = hdr.moh_first_cmd_off; load_end = load_array = (load_all_t *) xcalloc (sizeof (load_all_t), hdr.moh_n_load_cmds + 2); /* Build array of load commands, calculating the offsets */ for (i = 0; i < hdr.moh_n_load_cmds; i++) { load_union_t *load_hdr; /* load command header */ load_cmd = load_end++; load_hdr = (load_union_t *) (obj + offset); /* If modifying the program file, copy the header. */ if (rw) { load_union_t *ptr = (load_union_t *) xmalloc (load_hdr->hdr.ldci_cmd_size); bcopy ((generic *)load_hdr, (generic *)ptr, load_hdr->hdr.ldci_cmd_size); load_hdr = ptr; /* null out old command map, because we will rewrite at the end. */ if (ptr->hdr.ldci_cmd_type == LDC_CMD_MAP) { cmd_strings = ptr->map.lcm_ld_cmd_strings; ptr->hdr.ldci_cmd_type = LDC_UNDEFINED; } } load_cmd->load = load_hdr; if (load_hdr->hdr.ldci_section_off > 0) load_cmd->section = obj + load_hdr->hdr.ldci_section_off; if (debug) print_load_command (load_hdr, offset, i); offset += load_hdr->hdr.ldci_cmd_size; } /* If the last command is the load command map and is not undefined, decrement the count of load commands. */ if (rw && load_end[-1].load->hdr.ldci_cmd_type == LDC_UNDEFINED) { load_end--; hdr.moh_n_load_cmds--; } /* Go through and process each symbol table section. */ symbol_load_cmds = 0; for (load_cmd = load_array; load_cmd < load_end; load_cmd++) { load_union_t *load_hdr = load_cmd->load; if (load_hdr->hdr.ldci_cmd_type == LDC_SYMBOLS) { symbol_load_cmds++; if (debug) { char *kind = "unknown"; switch (load_hdr->sym.symc_kind) { case SYMC_IMPORTS: kind = "imports"; break; case SYMC_DEFINED_SYMBOLS: kind = "defined"; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -