/* Sets the default target if none has been given already. An empty string as the default target in interpreted as stdin. The string is quoted for MAKE. */ void deps_add_default_target (struct deps *d, const char *tgt) { /* Only if we have no targets. */ if (d->ntargets) return; if (tgt[0] == '\0') deps_add_target (d, "-", 1); else { #ifndef TARGET_OBJECT_SUFFIX # define TARGET_OBJECT_SUFFIX ".o" #endif const char *start = lbasename (tgt); char *o = alloca (strlen (start) + strlen (TARGET_OBJECT_SUFFIX) + 1); char *suffix; strcpy (o, start); suffix = strrchr (o, '.'); if (!suffix) suffix = o + strlen (o); strcpy (suffix, TARGET_OBJECT_SUFFIX); deps_add_target (d, o, 1); } }
static void handle_pragma_interface (cpp_reader* /*dfile*/) { tree fname = parse_strconst_pragma ("interface", 1); struct c_fileinfo *finfo; const char *filename; if (fname == error_mark_node) return; else if (fname == 0) filename = lbasename (LOCATION_FILE (input_location)); else filename = TREE_STRING_POINTER (fname); finfo = get_fileinfo (LOCATION_FILE (input_location)); if (impl_file_chain == 0) { /* If this is zero at this point, then we are auto-implementing. */ if (main_input_filename == 0) main_input_filename = LOCATION_FILE (input_location); } finfo->interface_only = interface_strcmp (filename); /* If MULTIPLE_SYMBOL_SPACES is set, we cannot assume that we can see a definition in another file. */ if (!MULTIPLE_SYMBOL_SPACES || !finfo->interface_only) finfo->interface_unknown = 0; }
/* * Create a string which describes a position in a source file. */ const char * mkpos(pos_t *posp) { size_t len; const char *fn; static char *buf; static size_t blen = 0; int qm, src, line; if (Hflag && posp->p_src != posp->p_isrc) { src = posp->p_isrc; line = posp->p_iline; } else { src = posp->p_src; line = posp->p_line; } qm = !Hflag && posp->p_src != posp->p_isrc; len = strlen(fn = lbasename(fnames[src])); len += 3 * sizeof (u_short) + 4; if (len > blen) buf = xrealloc(buf, blen = len); if (line != 0) { (void)sprintf(buf, "%s%s(%d)", fn, qm ? "?" : "", line); } else { (void)sprintf(buf, "%s", fn); } return (buf); }
SIM_RC sim_pre_argv_init (SIM_DESC sd, const char *myname) { SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); SIM_ASSERT (STATE_MODULES (sd) == NULL); STATE_MY_NAME (sd) = lbasename (myname); /* Set the cpu names to default values. */ { int i; for (i = 0; i < MAX_NR_PROCESSORS; ++i) { char *name; if (asprintf (&name, "cpu%d", i) < 0) return SIM_RC_FAIL; CPU_NAME (STATE_CPU (sd, i)) = name; } } sim_config_default (sd); /* Install all configured in modules. */ if (sim_module_install (sd) != SIM_RC_OK) return SIM_RC_FAIL; return SIM_RC_OK; }
bool nesc_filename(const char *name) { char *dot = strrchr(lbasename(name), '.'); if (dot) { if (!strcmp(dot, ".nc")) return TRUE; } return FALSE; /* C by default */ }
static char * get_plugin_base_name (const char *full_name) { /* First get the base name part of the full-path name, i.e. NAME.so. */ char *base_name = xstrdup (lbasename (full_name)); /* Then get rid of '.so' part of the name. */ strip_off_ending (base_name, strlen (base_name)); return base_name; }
static gdb_bfd_ref_ptr macho_check_dsym (struct objfile *objfile, std::string *filenamep) { size_t name_len = strlen (objfile_name (objfile)); size_t dsym_len = strlen (DSYM_SUFFIX); const char *base_name = lbasename (objfile_name (objfile)); size_t base_len = strlen (base_name); char *dsym_filename = (char *) alloca (name_len + dsym_len + base_len + 1); bfd_mach_o_load_command *main_uuid; bfd_mach_o_load_command *dsym_uuid; strcpy (dsym_filename, objfile_name (objfile)); strcpy (dsym_filename + name_len, DSYM_SUFFIX); strcpy (dsym_filename + name_len + dsym_len, base_name); if (access (dsym_filename, R_OK) != 0) return NULL; if (bfd_mach_o_lookup_command (objfile->obfd, BFD_MACH_O_LC_UUID, &main_uuid) == 0) { warning (_("can't find UUID in %s"), objfile_name (objfile)); return NULL; } gdb_bfd_ref_ptr dsym_bfd (gdb_bfd_openr (dsym_filename, gnutarget)); if (dsym_bfd == NULL) { warning (_("can't open dsym file %s"), dsym_filename); return NULL; } if (!bfd_check_format (dsym_bfd.get (), bfd_object)) { warning (_("bad dsym file format: %s"), bfd_errmsg (bfd_get_error ())); return NULL; } if (bfd_mach_o_lookup_command (dsym_bfd.get (), BFD_MACH_O_LC_UUID, &dsym_uuid) == 0) { warning (_("can't find UUID in %s"), dsym_filename); return NULL; } if (memcmp (dsym_uuid->command.uuid.uuid, main_uuid->command.uuid.uuid, sizeof (main_uuid->command.uuid.uuid))) { warning (_("dsym file UUID doesn't match the one in %s"), objfile_name (objfile)); return NULL; } *filenamep = std::string (dsym_filename); return dsym_bfd; }
char * fbsd_make_corefile_notes (bfd *obfd, int *note_size) { const struct regcache *regcache = get_current_regcache (); struct gdbarch *gdbarch = get_regcache_arch (regcache); gregset_t gregs; fpregset_t fpregs; char *note_data = NULL; Elf_Internal_Ehdr *i_ehdrp; const struct regset *regset; size_t size; /* Put a "FreeBSD" label in the ELF header. */ i_ehdrp = elf_elfheader (obfd); i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; gdb_assert (gdbarch_regset_from_core_section_p (gdbarch)); size = sizeof gregs; regset = gdbarch_regset_from_core_section (gdbarch, ".reg", size); gdb_assert (regset && regset->collect_regset); regset->collect_regset (regset, regcache, -1, &gregs, size); note_data = elfcore_write_prstatus (obfd, note_data, note_size, ptid_get_pid (inferior_ptid), find_stop_signal (), &gregs); size = sizeof fpregs; regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", size); gdb_assert (regset && regset->collect_regset); regset->collect_regset (regset, regcache, -1, &fpregs, size); note_data = elfcore_write_prfpreg (obfd, note_data, note_size, &fpregs, sizeof (fpregs)); if (get_exec_file (0)) { const char *fname = lbasename (get_exec_file (0)); char *psargs = xstrdup (fname); if (get_inferior_args ()) psargs = reconcat (psargs, psargs, " ", get_inferior_args (), (char *) NULL); note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, fname, psargs); } make_cleanup (xfree, note_data); return note_data; }
static void verror( int n, va_list ap) { const char *fn; if (ERR_ISSET(n, &msgset)) return; fn = lbasename(curr_pos.p_file); (void)printf("%s(%d): ", fn, curr_pos.p_line); (void)vprintf(msgs[n], ap); (void)printf(" [%d]\n", n); nerr++; }
void lerror(const char *msg, ...) { va_list ap; const char *fn; va_start(ap, msg); fn = lbasename(curr_pos.p_file); (void)fprintf(stderr, "%s(%d): lint error: ", fn, curr_pos.p_line); (void)vfprintf(stderr, msg, ap); (void)fprintf(stderr, "\n"); va_end(ap); exit(1); }
static void gldelf64ltsmip_stat_needed (lang_input_statement_type *s) { struct stat st; const char *suffix; const char *soname; if (global_found) return; if (s->the_bfd == NULL) return; if (bfd_stat (s->the_bfd, &st) != 0) { einfo ("%P:%B: bfd_stat failed: %E\n", s->the_bfd); return; } if (st.st_dev == global_stat.st_dev && st.st_ino == global_stat.st_ino) { global_found = TRUE; return; } /* We issue a warning if it looks like we are including two different versions of the same shared library. For example, there may be a problem if -lc picks up libc.so.6 but some other shared library has a DT_NEEDED entry of libc.so.5. This is a heuristic test, and it will only work if the name looks like NAME.so.VERSION. FIXME: Depending on file names is error-prone. If we really want to issue warnings about mixing version numbers of shared libraries, we need to find a better way. */ if (strchr (global_needed->name, '/') != NULL) return; suffix = strstr (global_needed->name, ".so."); if (suffix == NULL) return; suffix += sizeof ".so." - 1; soname = bfd_elf_get_dt_soname (s->the_bfd); if (soname == NULL) soname = lbasename (s->filename); if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0) einfo ("%P: warning: %s, needed by %B, may conflict with %s\n", global_needed->name, global_needed->by, soname); }
void message(int n, ...) { va_list ap; const char *fn; if (ERR_ISSET(n, &msgset)) return; va_start(ap, n); fn = lbasename(curr_pos.p_file); (void)printf("%s(%d): ", fn, curr_pos.p_line); (void)vprintf(msgs[n], ap); (void)printf(" [%d]\n", n); va_end(ap); }
static void gldelf64ltsmip_vercheck (lang_input_statement_type *s) { const char *soname; struct bfd_link_needed_list *l; if (global_vercheck_failed) return; if (s->the_bfd == NULL || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0) return; soname = bfd_elf_get_dt_soname (s->the_bfd); if (soname == NULL) soname = lbasename (bfd_get_filename (s->the_bfd)); for (l = global_vercheck_needed; l != NULL; l = l->next) { const char *suffix; if (strcmp (soname, l->name) == 0) { /* Probably can't happen, but it's an easy check. */ continue; } if (strchr (l->name, '/') != NULL) continue; suffix = strstr (l->name, ".so."); if (suffix == NULL) continue; suffix += sizeof ".so." - 1; if (strncmp (soname, l->name, suffix - l->name) == 0) { /* Here we know that S is a dynamic object FOO.SO.VER1, and the object we are considering needs a dynamic object FOO.SO.VER2, and VER1 and VER2 are different. This appears to be a version mismatch, so we tell the caller to try a different version of this library. */ global_vercheck_failed = TRUE; return; } } }
static void vwarning( int n, va_list ap) { const char *fn; if (ERR_ISSET(n, &msgset)) return; if (nowarn) /* this warning is suppressed by a LINTED comment */ return; fn = lbasename(curr_pos.p_file); (void)printf("%s(%d): warning: ", fn, curr_pos.p_line); (void)vprintf(msgs[n], ap); (void)printf(" [%d]\n", n); if (wflag) nerr++; }
gdb::unique_xmalloc_ptr<char> gdb_realpath_keepfile (const char *filename) { const char *base_name = lbasename (filename); char *dir_name; char *result; /* Extract the basename of filename, and return immediately a copy of filename if it does not contain any directory prefix. */ if (base_name == filename) return gdb::unique_xmalloc_ptr<char> (xstrdup (filename)); dir_name = (char *) alloca ((size_t) (base_name - filename + 2)); /* Allocate enough space to store the dir_name + plus one extra character sometimes needed under Windows (see below), and then the closing \000 character. */ strncpy (dir_name, filename, base_name - filename); dir_name[base_name - filename] = '\000'; #ifdef HAVE_DOS_BASED_FILE_SYSTEM /* We need to be careful when filename is of the form 'd:foo', which is equivalent of d:./foo, which is totally different from d:/foo. */ if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':') { dir_name[2] = '.'; dir_name[3] = '\000'; } #endif /* Canonicalize the directory prefix, and build the resulting filename. If the dirname realpath already contains an ending directory separator, avoid doubling it. */ gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name); const char *real_path = path_storage.get (); if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1])) result = concat (real_path, base_name, (char *) NULL); else result = concat (real_path, SLASH_STRING, base_name, (char *) NULL); return gdb::unique_xmalloc_ptr<char> (result); }
static char * fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) { struct regcache *regcache = get_current_regcache (); char *note_data; Elf_Internal_Ehdr *i_ehdrp; struct fbsd_collect_regset_section_cb_data data; /* Put a "FreeBSD" label in the ELF header. */ i_ehdrp = elf_elfheader (obfd); i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch)); data.regcache = regcache; data.obfd = obfd; data.note_data = NULL; data.note_size = note_size; target_fetch_registers (regcache, -1); gdbarch_iterate_over_regset_sections (gdbarch, fbsd_collect_regset_section_cb, &data, regcache); note_data = data.note_data; if (get_exec_file (0)) { const char *fname = lbasename (get_exec_file (0)); char *psargs = xstrdup (fname); if (get_inferior_args ()) psargs = reconcat (psargs, psargs, " ", get_inferior_args (), (char *) NULL); note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, fname, psargs); } return note_data; }
static void handle_pragma_implementation (cpp_reader* /*dfile*/) { tree fname = parse_strconst_pragma ("implementation", 1); const char *filename; struct impl_files *ifiles = impl_file_chain; if (fname == error_mark_node) return; if (fname == 0) { if (main_input_filename) filename = main_input_filename; else filename = LOCATION_FILE (input_location); filename = lbasename (filename); } else { filename = TREE_STRING_POINTER (fname); if (cpp_included_before (parse_in, filename, input_location)) warning (0, "#pragma implementation for %qs appears after " "file is included", filename); } for (; ifiles; ifiles = ifiles->next) { if (! filename_cmp (ifiles->filename, filename)) break; } if (ifiles == 0) { ifiles = XNEW (struct impl_files); ifiles->filename = xstrdup (filename); ifiles->next = impl_file_chain; impl_file_chain = ifiles; }
const char *element_name(region r, const char *path) /* Returns: Return the "identifier part" of path, i.e., remove any directory and extension The returned string is allocated in region r. */ { const char *base, *dot; base = lbasename(path); dot = strrchr(base, '.'); if (dot) { /* Extract id */ char *copy = rarrayalloc(r, dot - base + 1, char); memcpy(copy, base, dot - base); copy[dot - base] = '\0'; return copy; } else return rstrdup(r, base);
int main (int argc, char **argv) { const char *name; char **prog_argv = NULL; struct bfd *prog_bfd; enum sim_stop reason; int sigrc = 0; int single_step = 0; RETSIGTYPE (*prev_sigint) (); myname = lbasename (argv[0]); /* INTERNAL: When MYNAME is `step', single step the simulator instead of allowing it to run free. The sole purpose of this HACK is to allow the sim_resume interface's step argument to be tested without having to build/run gdb. */ if (strlen (myname) > 4 && strcmp (myname - 4, "step") == 0) { single_step = 1; } /* Create an instance of the simulator. */ default_callback.init (&default_callback); sd = sim_open (SIM_OPEN_STANDALONE, &default_callback, NULL, argv); if (sd == 0) exit (1); if (STATE_MAGIC (sd) != SIM_MAGIC_NUMBER) { fprintf (stderr, "Internal error - bad magic number in simulator struct\n"); abort (); } /* We can't set the endianness in the callback structure until sim_config is called, which happens in sim_open. */ default_callback.target_endian = (CURRENT_TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE); /* Was there a program to run? */ prog_argv = STATE_PROG_ARGV (sd); prog_bfd = STATE_PROG_BFD (sd); if (prog_argv == NULL || *prog_argv == NULL) usage (); name = *prog_argv; /* For simulators that don't open prog during sim_open() */ if (prog_bfd == NULL) { prog_bfd = bfd_openr (name, 0); if (prog_bfd == NULL) { fprintf (stderr, "%s: can't open \"%s\": %s\n", myname, name, bfd_errmsg (bfd_get_error ())); exit (1); } if (!bfd_check_format (prog_bfd, bfd_object)) { fprintf (stderr, "%s: \"%s\" is not an object file: %s\n", myname, name, bfd_errmsg (bfd_get_error ())); exit (1); } } if (STATE_VERBOSE_P (sd)) printf ("%s %s\n", myname, name); /* Load the program into the simulator. */ if (sim_load (sd, name, prog_bfd, 0) == SIM_RC_FAIL) exit (1); /* Prepare the program for execution. */ #ifdef HAVE_ENVIRON sim_create_inferior (sd, prog_bfd, prog_argv, environ); #else sim_create_inferior (sd, prog_bfd, prog_argv, NULL); #endif /* To accommodate relative file paths, chdir to sysroot now. We mustn't do this until BFD has opened the program, else we wouldn't find the executable if it has a relative file path. */ if (simulator_sysroot[0] != '\0' && chdir (simulator_sysroot) < 0) { fprintf (stderr, "%s: can't change directory to \"%s\"\n", myname, simulator_sysroot); exit (1); } /* Run/Step the program. */ if (single_step) { do { prev_sigint = signal (SIGINT, cntrl_c); sim_resume (sd, 1/*step*/, 0); signal (SIGINT, prev_sigint); sim_stop_reason (sd, &reason, &sigrc); if ((reason == sim_stopped) && (sigrc == sim_signal_to_host (sd, SIM_SIGINT))) break; /* exit on control-C */ } /* remain on breakpoint or signals in oe mode*/ while (((reason == sim_signalled) && (sigrc == sim_signal_to_host (sd, SIM_SIGTRAP))) || ((reason == sim_stopped) && (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT))); } else { do { #if defined (HAVE_SIGACTION) && defined (SA_RESTART) struct sigaction sa, osa; sa.sa_handler = cntrl_c; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (SIGINT, &sa, &osa); prev_sigint = osa.sa_handler; #else prev_sigint = signal (SIGINT, cntrl_c); #endif sim_resume (sd, 0, sigrc); signal (SIGINT, prev_sigint); sim_stop_reason (sd, &reason, &sigrc); if ((reason == sim_stopped) && (sigrc == sim_signal_to_host (sd, SIM_SIGINT))) break; /* exit on control-C */ /* remain on signals in oe mode */ } while ((reason == sim_stopped) && (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT)); } /* Print any stats the simulator collected. */ if (STATE_VERBOSE_P (sd)) sim_info (sd, 0); /* Shutdown the simulator. */ sim_close (sd, 0); /* If reason is sim_exited, then sigrc holds the exit code which we want to return. If reason is sim_stopped or sim_signalled, then sigrc holds the signal that the simulator received; we want to return that to indicate failure. */ /* Why did we stop? */ switch (reason) { case sim_signalled: case sim_stopped: if (sigrc != 0) fprintf (stderr, "program stopped with signal %d (%s).\n", sigrc, strsignal (sigrc)); break; case sim_exited: break; default: fprintf (stderr, "program in undefined state (%d:%d)\n", reason, sigrc); break; } return sigrc; }
static int bt_callback (void *data, uintptr_t pc, const char *filename, int lineno, const char *function) { int *pcount = (int *) data; /* If we don't have any useful information, don't print anything. */ if (filename == NULL && function == NULL) return 0; /* Skip functions in diagnostic.c. */ if (*pcount == 0 && filename != NULL && strcmp (lbasename (filename), "diagnostic.c") == 0) return 0; /* Print up to 20 functions. We could make this a --param, but since this is only for debugging just use a constant for now. */ if (*pcount >= 20) { /* Returning a non-zero value stops the backtrace. */ return 1; } ++*pcount; char *alc = NULL; if (function != NULL) { char *str = cplus_demangle_v3 (function, (DMGL_VERBOSE | DMGL_ANSI | DMGL_GNU_V3 | DMGL_PARAMS)); if (str != NULL) { alc = str; function = str; } for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i) { size_t len = strlen (bt_stop[i]); if (strncmp (function, bt_stop[i], len) == 0 && (function[len] == '\0' || function[len] == '(')) { if (alc != NULL) free (alc); /* Returning a non-zero value stops the backtrace. */ return 1; } } } fprintf (stderr, "0x%lx %s\n\t%s:%d\n", (unsigned long) pc, function == NULL ? "???" : function, filename == NULL ? "???" : filename, lineno); if (alc != NULL) free (alc); return 0; }
static const char * debug_objfile_name (const struct objfile *objfile) { return lbasename (objfile->original_name); }
static void dequeue_and_dump (dump_info_p di) { dump_queue_p dq; splay_tree_node stn; dump_node_info_p dni; tree t; unsigned int index; enum tree_code code; enum tree_code_class code_class; const char* code_name; /* Get the next node from the queue. */ dq = di->queue; stn = dq->node; t = (tree) stn->key; dni = (dump_node_info_p) stn->value; index = dni->index; /* Remove the node from the queue, and put it on the free list. */ di->queue = dq->next; if (!di->queue) di->queue_end = 0; dq->next = di->free_list; di->free_list = dq; /* Print the node index. */ dump_index (di, index); /* And the type of node this is. */ if (dni->binfo_p) code_name = "binfo"; else code_name = tree_code_name[(int) TREE_CODE (t)]; fprintf (di->stream, "%-16s ", code_name); di->column = 25; /* Figure out what kind of node this is. */ code = TREE_CODE (t); code_class = TREE_CODE_CLASS (code); /* Although BINFOs are TREE_VECs, we dump them specially so as to be more informative. */ if (dni->binfo_p) { unsigned ix; tree base; VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t); dump_child ("type", BINFO_TYPE (t)); if (BINFO_VIRTUAL_P (t)) dump_string_field (di, "spec", "virt"); dump_int (di, "bases", BINFO_N_BASE_BINFOS (t)); for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++) { tree access = (accesses ? VEC_index (tree, accesses, ix) : access_public_node); const char *string = NULL; if (access == access_public_node) string = "pub"; else if (access == access_protected_node) string = "prot"; else if (access == access_private_node) string = "priv"; else gcc_unreachable (); dump_string_field (di, "accs", string); queue_and_dump_index (di, "binf", base, DUMP_BINFO); } goto done; } /* We can knock off a bunch of expression nodes in exactly the same way. */ if (IS_EXPR_CODE_CLASS (code_class)) { /* If we're dumping children, dump them now. */ queue_and_dump_type (di, t); switch (code_class) { case tcc_unary: dump_child ("op 0", TREE_OPERAND (t, 0)); break; case tcc_binary: case tcc_comparison: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; case tcc_expression: case tcc_reference: case tcc_statement: case tcc_vl_exp: /* These nodes are handled explicitly below. */ break; default: gcc_unreachable (); } } else if (DECL_P (t)) { expanded_location xloc; /* All declarations have names. */ if (DECL_NAME (t)) dump_child ("name", DECL_NAME (t)); if (DECL_ASSEMBLER_NAME_SET_P (t) && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t)) dump_child ("mngl", DECL_ASSEMBLER_NAME (t)); if (DECL_ABSTRACT_ORIGIN (t)) dump_child ("orig", DECL_ABSTRACT_ORIGIN (t)); /* And types. */ queue_and_dump_type (di, t); dump_child ("scpe", DECL_CONTEXT (t)); /* And a source position. */ xloc = expand_location (DECL_SOURCE_LOCATION (t)); if (xloc.file) { const char *filename = lbasename (xloc.file); dump_maybe_newline (di); fprintf (di->stream, "srcp: %s:%-6d ", filename, xloc.line); di->column += 6 + strlen (filename) + 8; } /* And any declaration can be compiler-generated. */ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON) && DECL_ARTIFICIAL (t)) dump_string_field (di, "note", "artificial"); if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL)) dump_child ("chain", DECL_CHAIN (t)); } else if (code_class == tcc_type) { /* All types have qualifiers. */ int quals = lang_hooks.tree_dump.type_quals (t); if (quals != TYPE_UNQUALIFIED) { fprintf (di->stream, "qual: %c%c%c ", (quals & TYPE_QUAL_CONST) ? 'c' : ' ', (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ', (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' '); di->column += 14; } /* All types have associated declarations. */ dump_child ("name", TYPE_NAME (t)); /* All types have a main variant. */ if (TYPE_MAIN_VARIANT (t) != t) dump_child ("unql", TYPE_MAIN_VARIANT (t)); /* And sizes. */ dump_child ("size", TYPE_SIZE (t)); /* All types have alignments. */ dump_int (di, "algn", TYPE_ALIGN (t)); } else if (code_class == tcc_constant) /* All constants can have types. */ queue_and_dump_type (di, t); /* Give the language-specific code a chance to print something. If it's completely taken care of things, don't bother printing anything more ourselves. */ if (lang_hooks.tree_dump.dump_tree (di, t)) goto done; /* Now handle the various kinds of nodes. */ switch (code) { int i; case IDENTIFIER_NODE: dump_string_field (di, "strg", IDENTIFIER_POINTER (t)); dump_int (di, "lngt", IDENTIFIER_LENGTH (t)); break; case TREE_LIST: dump_child ("purp", TREE_PURPOSE (t)); dump_child ("valu", TREE_VALUE (t)); dump_child ("chan", TREE_CHAIN (t)); break; case STATEMENT_LIST: { tree_stmt_iterator it; for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++) { char buffer[32]; sprintf (buffer, "%u", i); dump_child (buffer, tsi_stmt (it)); } } break; case TREE_VEC: dump_int (di, "lngt", TREE_VEC_LENGTH (t)); for (i = 0; i < TREE_VEC_LENGTH (t); ++i) { char buffer[32]; sprintf (buffer, "%u", i); dump_child (buffer, TREE_VEC_ELT (t, i)); } break; case INTEGER_TYPE: case ENUMERAL_TYPE: dump_int (di, "prec", TYPE_PRECISION (t)); dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed"); dump_child ("min", TYPE_MIN_VALUE (t)); dump_child ("max", TYPE_MAX_VALUE (t)); if (code == ENUMERAL_TYPE) dump_child ("csts", TYPE_VALUES (t)); break; case REAL_TYPE: dump_int (di, "prec", TYPE_PRECISION (t)); break; case FIXED_POINT_TYPE: dump_int (di, "prec", TYPE_PRECISION (t)); dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed"); dump_string_field (di, "saturating", TYPE_SATURATING (t) ? "saturating": "non-saturating"); break; case POINTER_TYPE: dump_child ("ptd", TREE_TYPE (t)); break; case REFERENCE_TYPE: dump_child ("refd", TREE_TYPE (t)); break; case METHOD_TYPE: dump_child ("clas", TYPE_METHOD_BASETYPE (t)); /* Fall through. */ case FUNCTION_TYPE: dump_child ("retn", TREE_TYPE (t)); dump_child ("prms", TYPE_ARG_TYPES (t)); break; case ARRAY_TYPE: dump_child ("elts", TREE_TYPE (t)); dump_child ("domn", TYPE_DOMAIN (t)); break; case RECORD_TYPE: case UNION_TYPE: if (TREE_CODE (t) == RECORD_TYPE) dump_string_field (di, "tag", "struct"); else dump_string_field (di, "tag", "union"); dump_child ("flds", TYPE_FIELDS (t)); dump_child ("fncs", TYPE_METHODS (t)); queue_and_dump_index (di, "binf", TYPE_BINFO (t), DUMP_BINFO); break; case CONST_DECL: dump_child ("cnst", DECL_INITIAL (t)); break; case DEBUG_EXPR_DECL: dump_int (di, "-uid", DEBUG_TEMP_UID (t)); /* Fall through. */ case VAR_DECL: case PARM_DECL: case FIELD_DECL: case RESULT_DECL: if (TREE_CODE (t) == PARM_DECL) dump_child ("argt", DECL_ARG_TYPE (t)); else dump_child ("init", DECL_INITIAL (t)); dump_child ("size", DECL_SIZE (t)); dump_int (di, "algn", DECL_ALIGN (t)); if (TREE_CODE (t) == FIELD_DECL) { if (DECL_FIELD_OFFSET (t)) dump_child ("bpos", bit_position (t)); } else if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) { dump_int (di, "used", TREE_USED (t)); if (DECL_REGISTER (t)) dump_string_field (di, "spec", "register"); } break; case FUNCTION_DECL: dump_child ("args", DECL_ARGUMENTS (t)); if (DECL_EXTERNAL (t)) dump_string_field (di, "body", "undefined"); if (TREE_PUBLIC (t)) dump_string_field (di, "link", "extern"); else dump_string_field (di, "link", "static"); if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t)) dump_child ("body", DECL_SAVED_TREE (t)); break; case INTEGER_CST: if (TREE_INT_CST_HIGH (t)) dump_int (di, "high", TREE_INT_CST_HIGH (t)); dump_int (di, "low", TREE_INT_CST_LOW (t)); break; case STRING_CST: fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t)); dump_int (di, "lngt", TREE_STRING_LENGTH (t)); break; case REAL_CST: dump_real (di, "valu", TREE_REAL_CST_PTR (t)); break; case FIXED_CST: dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t)); break; case TRUTH_NOT_EXPR: case ADDR_EXPR: case INDIRECT_REF: case CLEANUP_POINT_EXPR: case SAVE_EXPR: case REALPART_EXPR: case IMAGPART_EXPR: /* These nodes are unary, but do not have code class `1'. */ dump_child ("op 0", TREE_OPERAND (t, 0)); break; case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: case INIT_EXPR: case MODIFY_EXPR: case COMPOUND_EXPR: case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: /* These nodes are binary, but do not have code class `2'. */ dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; case COMPONENT_REF: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); dump_child ("op 2", TREE_OPERAND (t, 2)); break; case ARRAY_REF: case ARRAY_RANGE_REF: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); dump_child ("op 2", TREE_OPERAND (t, 2)); dump_child ("op 3", TREE_OPERAND (t, 3)); break; case COND_EXPR: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); dump_child ("op 2", TREE_OPERAND (t, 2)); break; case TRY_FINALLY_EXPR: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; case CALL_EXPR: { int i = 0; tree arg; call_expr_arg_iterator iter; dump_child ("fn", CALL_EXPR_FN (t)); FOR_EACH_CALL_EXPR_ARG (arg, iter, t) { char buffer[32]; sprintf (buffer, "%u", i); dump_child (buffer, arg); i++; } } break; case CONSTRUCTOR: { unsigned HOST_WIDE_INT cnt; tree index, value; dump_int (di, "lngt", VEC_length (constructor_elt, CONSTRUCTOR_ELTS (t))); FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value) { dump_child ("idx", index); dump_child ("val", value); } }
struct bound_minimal_symbol lookup_minimal_symbol (const char *name, const char *sfile, struct objfile *objf) { struct objfile *objfile; found_minimal_symbols found; unsigned int mangled_hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE; auto *mangled_cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp); if (sfile != NULL) sfile = lbasename (sfile); lookup_name_info lookup_name (name, symbol_name_match_type::FULL); for (objfile = object_files; objfile != NULL && found.external_symbol.minsym == NULL; objfile = objfile->next) { if (objf == NULL || objf == objfile || objf == objfile->separate_debug_objfile_backlink) { if (symbol_lookup_debug) { fprintf_unfiltered (gdb_stdlog, "lookup_minimal_symbol (%s, %s, %s)\n", name, sfile != NULL ? sfile : "NULL", objfile_debug_name (objfile)); } /* Do two passes: the first over the ordinary hash table, and the second over the demangled hash table. */ lookup_minimal_symbol_mangled (name, sfile, objfile, objfile->per_bfd->msymbol_hash, mangled_hash, mangled_cmp, found); /* If not found, try the demangled hash table. */ if (found.external_symbol.minsym == NULL) { /* Once for each language in the demangled hash names table (usually just zero or one languages). */ for (auto lang : objfile->per_bfd->demangled_hash_languages) { unsigned int hash = (lookup_name.search_name_hash (lang) % MINIMAL_SYMBOL_HASH_SIZE); symbol_name_matcher_ftype *match = get_symbol_name_matcher (language_def (lang), lookup_name); struct minimal_symbol **msymbol_demangled_hash = objfile->per_bfd->msymbol_demangled_hash; lookup_minimal_symbol_demangled (lookup_name, sfile, objfile, msymbol_demangled_hash, hash, match, found); if (found.external_symbol.minsym != NULL) break; } } } } /* External symbols are best. */ if (found.external_symbol.minsym != NULL) { if (symbol_lookup_debug) { minimal_symbol *minsym = found.external_symbol.minsym; fprintf_unfiltered (gdb_stdlog, "lookup_minimal_symbol (...) = %s (external)\n", host_address_to_string (minsym)); } return found.external_symbol; } /* File-local symbols are next best. */ if (found.file_symbol.minsym != NULL) { if (symbol_lookup_debug) { minimal_symbol *minsym = found.file_symbol.minsym; fprintf_unfiltered (gdb_stdlog, "lookup_minimal_symbol (...) = %s (file-local)\n", host_address_to_string (minsym)); } return found.file_symbol; } /* Symbols for shared library trampolines are next best. */ if (found.trampoline_symbol.minsym != NULL) { if (symbol_lookup_debug) { minimal_symbol *minsym = found.trampoline_symbol.minsym; fprintf_unfiltered (gdb_stdlog, "lookup_minimal_symbol (...) = %s (trampoline)\n", host_address_to_string (minsym)); } return found.trampoline_symbol; } /* Not found. */ if (symbol_lookup_debug) fprintf_unfiltered (gdb_stdlog, "lookup_minimal_symbol (...) = NULL\n"); return {}; }
/* Return the portion of PATHNAME that should be output when listing possible completions. If we are hacking filename completion, we are only interested in the basename, the portion following the final slash. Otherwise, we return what we were passed. Comes from readline/complete.c. */ static const char * printable_part (const char *pathname) { return rl_filename_completion_desired ? lbasename (pathname) : pathname; }
static unsigned int get_filenum (const char *filename, unsigned int num) { static unsigned int last_used, last_used_dir_len; const char *file; size_t dir_len; unsigned int i, dir; if (num == 0 && last_used) { if (! files[last_used].dir && filename_cmp (filename, files[last_used].filename) == 0) return last_used; if (files[last_used].dir && filename_ncmp (filename, dirs[files[last_used].dir], last_used_dir_len) == 0 && IS_DIR_SEPARATOR (filename [last_used_dir_len]) && filename_cmp (filename + last_used_dir_len + 1, files[last_used].filename) == 0) return last_used; } file = lbasename (filename); /* Don't make empty string from / or A: from A:/ . */ #ifdef HAVE_DOS_BASED_FILE_SYSTEM if (file <= filename + 3) file = filename; #else if (file == filename + 1) file = filename; #endif dir_len = file - filename; dir = 0; if (dir_len) { #ifndef DWARF2_DIR_SHOULD_END_WITH_SEPARATOR --dir_len; #endif for (dir = 1; dir < dirs_in_use; ++dir) if (filename_ncmp (filename, dirs[dir], dir_len) == 0 && dirs[dir][dir_len] == '\0') break; if (dir >= dirs_in_use) { if (dir >= dirs_allocated) { dirs_allocated = dir + 32; dirs = (char **) xrealloc (dirs, (dir + 32) * sizeof (const char *)); } dirs[dir] = (char *) xmalloc (dir_len + 1); memcpy (dirs[dir], filename, dir_len); dirs[dir][dir_len] = '\0'; dirs_in_use = dir + 1; } } if (num == 0) { for (i = 1; i < files_in_use; ++i) if (files[i].dir == dir && files[i].filename && filename_cmp (file, files[i].filename) == 0) { last_used = i; last_used_dir_len = dir_len; return i; } } else i = num; if (i >= files_allocated) { unsigned int old = files_allocated; files_allocated = i + 32; files = (struct file_entry *) xrealloc (files, (i + 32) * sizeof (struct file_entry)); memset (files + old, 0, (i + 32 - old) * sizeof (struct file_entry)); } files[i].filename = num ? file : xstrdup (file); files[i].dir = dir; if (files_in_use < i + 1) files_in_use = i + 1; last_used = i; last_used_dir_len = dir_len; return i; }
static bfd_boolean gldelf64ltsmip_try_needed (const char *name, int force) { bfd *abfd; const char *soname; abfd = bfd_openr (name, bfd_get_target (output_bfd)); if (abfd == NULL) return FALSE; if (! bfd_check_format (abfd, bfd_object)) { bfd_close (abfd); return FALSE; } if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) { bfd_close (abfd); return FALSE; } /* For DT_NEEDED, they have to match. */ if (abfd->xvec != output_bfd->xvec) { bfd_close (abfd); return FALSE; } /* Check whether this object would include any conflicting library versions. If FORCE is set, then we skip this check; we use this the second time around, if we couldn't find any compatible instance of the shared library. */ if (! force) { struct bfd_link_needed_list *needed; if (! bfd_elf_get_bfd_needed_list (abfd, &needed)) einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd); if (needed != NULL) { global_vercheck_needed = needed; global_vercheck_failed = FALSE; lang_for_each_input_file (gldelf64ltsmip_vercheck); if (global_vercheck_failed) { bfd_close (abfd); /* Return FALSE to force the caller to move on to try another file on the search path. */ return FALSE; } /* But wait! It gets much worse. On Linux, if a shared library does not use libc at all, we are supposed to skip it the first time around in case we encounter a shared library later on with the same name which does use the version of libc that we want. This is much too horrible to use on any system other than Linux. */ { struct bfd_link_needed_list *l; for (l = needed; l != NULL; l = l->next) if (strncmp (l->name, "libc.so", 7) == 0) break; if (l == NULL) { bfd_close (abfd); return FALSE; } } } } /* We've found a dynamic object matching the DT_NEEDED entry. */ /* We have already checked that there is no other input file of the same name. We must now check again that we are not including the same file twice. We need to do this because on many systems libc.so is a symlink to, e.g., libc.so.1. The SONAME entry will reference libc.so.1. If we have already included libc.so, we don't want to include libc.so.1 if they are the same file, and we can only check that using stat. */ if (bfd_stat (abfd, &global_stat) != 0) einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd); /* First strip off everything before the last '/'. */ soname = lbasename (abfd->filename); if (trace_file_tries) info_msg (_("found %s at %s\n"), soname, name); global_found = FALSE; lang_for_each_input_file (gldelf64ltsmip_stat_needed); if (global_found) { /* Return TRUE to indicate that we found the file, even though we aren't going to do anything with it. */ return TRUE; } /* Tell the ELF backend that we don't want the output file to have a DT_NEEDED entry for this file. */ bfd_elf_set_dt_needed_name (abfd, ""); /* Tell the ELF backend that the output file needs a DT_NEEDED entry for this file if it is used to resolve the reference in a regular object. */ bfd_elf_set_dt_needed_soname (abfd, soname); /* 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; }
void lang_specific_driver (cl_decoded_option **in_decoded_options, unsigned int *in_decoded_options_count, int *in_added_libraries) { int i, j; /* If nonzero, the user gave us the `-p' or `-pg' flag. */ int saw_profile_flag = 0; /* Used by -debuglib */ int saw_debug_flag = 0; /* What do with libgphobos: -1 means we should not link in libgphobos 0 means we should link in libgphobos if it is needed 1 means libgphobos is needed and should be linked in. 2 means libgphobos is needed and should be linked statically. */ int library = 0; /* If nonzero, use the standard D runtime library when linking with standard libraries. */ int phobos = 1; /* The number of arguments being added to what's in argv, other than libraries. We use this to track the number of times we've inserted -xd/-xnone. */ int added = 0; /* The new argument list will be contained in this. */ cl_decoded_option *new_decoded_options; /* "-lm" or "-lmath" if it appears on the command line. */ const cl_decoded_option *saw_math = 0; /* "-lpthread" if it appears on the command line. */ const cl_decoded_option *saw_thread = 0; /* "-lrt" if it appears on the command line. */ const cl_decoded_option *saw_time = 0; /* "-lc" if it appears on the command line. */ const cl_decoded_option *saw_libc = 0; /* "-lstdc++" if it appears on the command line. */ const cl_decoded_option *saw_libcxx = 0; /* An array used to flag each argument that needs a bit set for DSOURCE, MATHLIB, WITHTHREAD, WITHLIBC or WITHLIBCXX. */ int *args; /* Whether we need the C++ STD library. */ int need_stdcxx = 0; /* By default, we throw on the math library if we have one. */ int need_math = (MATH_LIBRARY[0] != '\0'); /* Whether we need the thread library. */ int need_thread = (THREAD_LIBRARY[0] != '\0'); /* By default, we throw on the time library if we have one. */ int need_time = (TIME_LIBRARY[0] != '\0'); /* True if we saw -static. */ int static_link = 0; /* True if we should add -shared-libgcc to the command-line. */ int shared_libgcc = 1; /* The total number of arguments with the new stuff. */ int argc; /* The argument list. */ cl_decoded_option *decoded_options; /* What default library to use instead of phobos */ const char *defaultlib = NULL; /* What debug library to use instead of phobos */ const char *debuglib = NULL; /* The number of libraries added in. */ int added_libraries; /* The total number of arguments with the new stuff. */ int num_args = 1; /* "-fonly" if it appears on the command line. */ const char *only_source_option = 0; /* Whether the -o option was used. */ int saw_opt_o = 0; /* The first input file with an extension of .d. */ const char *first_d_file = NULL; argc = *in_decoded_options_count; decoded_options = *in_decoded_options; added_libraries = *in_added_libraries; args = XCNEWVEC (int, argc); for (i = 1; i < argc; i++) { const char *arg = decoded_options[i].arg; switch (decoded_options[i].opt_index) { case OPT_nostdlib: case OPT_nodefaultlibs: library = -1; break; case OPT_nophoboslib: added = 1; // force argument rebuild phobos = 0; args[i] |= SKIPOPT; break; case OPT_defaultlib_: added = 1; phobos = 0; args[i] |= SKIPOPT; if (defaultlib != NULL) free (CONST_CAST (char *, defaultlib)); if (arg == NULL) error ("missing argument to 'defaultlib=' option"); else { defaultlib = XNEWVEC (char, strlen (arg)); strcpy (CONST_CAST (char *, defaultlib), arg); } break; case OPT_debuglib_: added = 1; phobos = 0; args[i] |= SKIPOPT; if (debuglib != NULL) free (CONST_CAST (char *, debuglib)); if (arg == NULL) error ("missing argument to 'debuglib=' option"); else { debuglib = XNEWVEC (char, strlen (arg)); strcpy (CONST_CAST (char *, debuglib), arg); } break; case OPT_l: if ((strcmp (arg, LIBSTDCXX) == 0) || (strcmp (arg, LIBSTDCXX_PROFILE) == 0)) { args[i] |= WITHLIBCXX; need_stdcxx = 0; } else if ((strcmp (arg, MATH_LIBRARY) == 0) || (strcmp (arg, MATH_LIBRARY_PROFILE) == 0)) { args[i] |= MATHLIB; need_math = 0; } else if (strcmp (arg, THREAD_LIBRARY) == 0) { args[i] |= WITHTHREAD; need_thread = 0; } else if (strcmp (arg, TIME_LIBRARY) == 0) { args[i] |= TIMELIB; need_time = 0; } else if (strcmp (arg, "c") == 0) args[i] |= WITHLIBC; else /* Unrecognized libraries (e.g. -ltango) may require libphobos. */ library = (library == 0) ? 1 : library; break; case OPT_pg: case OPT_p: saw_profile_flag++; break; case OPT_g: saw_debug_flag = 1; case OPT_v: /* If they only gave us `-v', don't try to link in libphobos. */ if (argc == 2) library = 0; break; case OPT_x: if (library == 0 && (strcmp (arg, "d") == 0)) library = 1; break; case OPT_Xlinker: case OPT_Wl_: /* Arguments that go directly to the linker might be .o files or something, and so might cause libphobos to be needed. */ if (library == 0) library = 1; break; case OPT_c: case OPT_S: case OPT_E: case OPT_M: case OPT_MM: case OPT_fsyntax_only: /* Don't specify libaries if we won't link, since that would cause a warning. */ library = -1; break; case OPT_o: saw_opt_o = 1; break; case OPT_static: static_link = 1; break; case OPT_static_libgcc: shared_libgcc = 0; break; case OPT_static_libphobos: library = library >= 0 ? 2 : library; args[i] |= SKIPOPT; break; case OPT_fonly_: args[i] |= SKIPOPT; only_source_option = decoded_options[i].orig_option_with_args_text; if (arg != NULL) { int len = strlen (only_source_option); if (len <= 2 || only_source_option[len-1] != 'd' || only_source_option[len-2] != '.') only_source_option = concat (only_source_option, ".d", NULL); } break; case OPT_SPECIAL_input_file: { int len; if (arg[0] == '\0' || arg[1] == '\0') continue; len = strlen (arg); /* Record that this is a D source file. */ if (len <= 2 || strcmp (arg + len - 2, ".d") == 0) { if (first_d_file == NULL) first_d_file = arg; args[i] |= DSOURCE; } /* If we don't know that this is a interface file, we might need to be link against libphobos library. */ if (library == 0) { if (len <= 3 || strcmp (arg + len - 3, ".di") != 0) library = 1; } /* If this is a C++ source file, we'll need to link against libstdc++ library. */ if ((len <= 3 || strcmp (arg + len - 3, ".cc") == 0) || (len <= 4 || strcmp (arg + len - 4, ".cpp") == 0) || (len <= 4 || strcmp (arg + len - 4, ".c++") == 0)) need_stdcxx = 1; break; } } } /* If we know we don't have to do anything, bail now. */ if (!added && library <= 0 && !only_source_option) { free (args); return; } /* There's no point adding -shared-libgcc if we don't have a shared libgcc. */ #ifndef ENABLE_SHARED_LIBGCC shared_libgcc = 0; #endif /* Make sure to have room for the trailing NULL argument. */ /* There is one extra argument added here for the runtime library: -lgphobos. The -pthread argument is added by setting need_thread. */ num_args = argc + added + need_math + shared_libgcc + (library > 0) * 5 + 2; new_decoded_options = XNEWVEC (cl_decoded_option, num_args); i = 0; j = 0; /* Copy the 0th argument, i.e., the name of the program itself. */ new_decoded_options[j++] = decoded_options[i++]; /* NOTE: We start at 1 now, not 0. */ while (i < argc) { if (args[i] & SKIPOPT) { ++i; continue; } new_decoded_options[j] = decoded_options[i]; /* Make sure -lphobos is before the math library, since libphobos itself uses those math routines. */ if (!saw_math && (args[i] & MATHLIB) && library > 0) { --j; saw_math = &decoded_options[i]; } if (!saw_thread && (args[i] & WITHTHREAD) && library > 0) { --j; saw_thread = &decoded_options[i]; } if (!saw_time && (args[i] & TIMELIB) && library > 0) { --j; saw_time = &decoded_options[i]; } if (!saw_libc && (args[i] & WITHLIBC) && library > 0) { --j; saw_libc = &decoded_options[i]; } if (!saw_libcxx && (args[i] & WITHLIBCXX) && library > 0) { --j; saw_libcxx = &decoded_options[i]; } if (args[i] & DSOURCE) { if (only_source_option) --j; } i++; j++; } if (only_source_option) { const char *only_source_arg = only_source_option + 7; generate_option (OPT_fonly_, only_source_arg, 1, CL_DRIVER, &new_decoded_options[j]); j++; generate_option_input_file (only_source_arg, &new_decoded_options[j++]); } /* If we are not linking, add a -o option. This is because we need the driver to pass all .d files to cc1d. Without a -o option the driver will invoke cc1d separately for each input file. */ if (library < 0 && first_d_file != NULL && !saw_opt_o) { const char *base; int baselen; int alen; char *out; base = lbasename (first_d_file); baselen = strlen (base) - 2; alen = baselen + 3; out = XNEWVEC (char, alen); memcpy (out, base, baselen); /* The driver will convert .o to some other suffix if appropriate. */ out[baselen] = '.'; out[baselen + 1] = 'o'; out[baselen + 2] = '\0'; generate_option (OPT_o, out, 1, CL_DRIVER, &new_decoded_options[j]); j++; } /* Add `-lgphobos' if we haven't already done so. */ if (library > 0 && phobos) { #ifdef HAVE_LD_STATIC_DYNAMIC if (library > 1 && !static_link) { generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER, &new_decoded_options[j]); j++; } #endif generate_option (OPT_l, saw_profile_flag ? LIBPHOBOS_PROFILE : LIBPHOBOS, 1, CL_DRIVER, &new_decoded_options[j]); added_libraries++; j++; generate_option (OPT_l, saw_profile_flag ? LIBDRUNTIME_PROFILE : LIBDRUNTIME, 1, CL_DRIVER, &new_decoded_options[j]); added_libraries++; j++; #ifdef HAVE_LD_STATIC_DYNAMIC if (library > 1 && !static_link) { generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER, &new_decoded_options[j]); j++; } #endif } else if (saw_debug_flag && debuglib) { generate_option (OPT_l, debuglib, 1, CL_DRIVER, &new_decoded_options[j++]); added_libraries++; } else if (defaultlib) { generate_option (OPT_l, defaultlib, 1, CL_DRIVER, &new_decoded_options[j++]); added_libraries++; } if (saw_libcxx) new_decoded_options[j++] = *saw_libcxx; else if (library > 0 && need_stdcxx) { generate_option (OPT_l, (saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX), 1, CL_DRIVER, &new_decoded_options[j++]); added_libraries++; } if (saw_math) new_decoded_options[j++] = *saw_math; else if (library > 0 && need_math) { generate_option (OPT_l, (saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY), 1, CL_DRIVER, &new_decoded_options[j++]); added_libraries++; } if (saw_thread) new_decoded_options[j++] = *saw_thread; else if (library > 0 && need_thread) { generate_option (OPT_l, THREAD_LIBRARY, 1, CL_DRIVER, &new_decoded_options[j++]); added_libraries++; } if (saw_time) new_decoded_options[j++] = *saw_time; else if (library > 0 && need_time) { generate_option (OPT_l, TIME_LIBRARY, 1, CL_DRIVER, &new_decoded_options[j++]); added_libraries++; } if (saw_libc) new_decoded_options[j++] = *saw_libc; if (shared_libgcc && !static_link) { generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER, &new_decoded_options[j++]); } *in_decoded_options_count = j; *in_decoded_options = new_decoded_options; *in_added_libraries = added_libraries; }
static bfd_boolean gldelf64ltsmip_open_dynamic_archive (const char *arch, search_dirs_type *search, lang_input_statement_type *entry) { const char *filename; char *string; if (! entry->is_archive) return FALSE; filename = entry->filename; /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION is defined, but it does not seem worth the headache to optimize away those two bytes of space. */ string = (char *) xmalloc (strlen (search->name) + strlen (filename) + strlen (arch) #ifdef EXTRA_SHLIB_EXTENSION + strlen (EXTRA_SHLIB_EXTENSION) #endif + sizeof "/lib.so"); sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); #ifdef EXTRA_SHLIB_EXTENSION /* Try the .so extension first. If that fails build a new filename using EXTRA_SHLIB_EXTENSION. */ if (! ldfile_try_open_bfd (string, entry)) sprintf (string, "%s/lib%s%s%s", search->name, filename, arch, EXTRA_SHLIB_EXTENSION); #endif if (! ldfile_try_open_bfd (string, entry)) { free (string); return FALSE; } entry->filename = string; /* We have found a dynamic object to include in the link. The ELF backend linker will create a DT_NEEDED entry in the .dynamic section naming this file. If this file includes a DT_SONAME entry, it will be used. Otherwise, the ELF linker will just use the name of the file. For an archive found by searching, like this one, the DT_NEEDED entry should consist of just the name of the file, without the path information used to find it. Note that we only need to do this if we have a dynamic object; an archive will never be referenced by a DT_NEEDED entry. FIXME: This approach--using bfd_elf_set_dt_needed_name--is not very pretty. I haven't been able to think of anything that is pretty, though. */ if (bfd_check_format (entry->the_bfd, bfd_object) && (entry->the_bfd->flags & DYNAMIC) != 0) { ASSERT (entry->is_archive && entry->search_dirs_flag); /* Rather than duplicating the logic above. Just use the filename we recorded earlier. */ filename = lbasename (entry->filename); bfd_elf_set_dt_needed_name (entry->the_bfd, filename); } return TRUE; }
void lang_specific_driver (struct cl_decoded_option **in_decoded_options, unsigned int *in_decoded_options_count, int *in_added_libraries) { unsigned int i, j; /* If true, the user gave us the `-p' or `-pg' flag. */ bool saw_profile_flag = false; /* This is a tristate: -1 means we should not link in libgo 0 means we should link in libgo if it is needed 1 means libgo is needed and should be linked in. 2 means libgo is needed and should be linked statically. */ int library = 0; /* The new argument list will be contained in this. */ struct cl_decoded_option *new_decoded_options; /* "-lm" or "-lmath" if it appears on the command line. */ const struct cl_decoded_option *saw_math = 0; /* "-lpthread" if it appears on the command line. */ const struct cl_decoded_option *saw_thread = 0; /* "-lc" if it appears on the command line. */ const struct cl_decoded_option *saw_libc = 0; /* An array used to flag each argument that needs a bit set for LANGSPEC, MATHLIB, or WITHLIBC. */ int *args; /* Whether we need the thread library. */ int need_thread = 0; /* By default, we throw on the math library if we have one. */ int need_math = (MATH_LIBRARY[0] != '\0'); /* True if we saw -static. */ int static_link = 0; /* True if we should add -shared-libgcc to the command-line. */ int shared_libgcc = 1; /* The total number of arguments with the new stuff. */ unsigned int argc; /* The argument list. */ struct cl_decoded_option *decoded_options; /* The number of libraries added in. */ int added_libraries; /* The total number of arguments with the new stuff. */ int num_args = 1; /* Whether the -o option was used. */ bool saw_opt_o = false; /* Whether the -c option was used. Also used for -E, -fsyntax-only, in general anything which implies only compilation and not linking. */ bool saw_opt_c = false; /* Whether the -S option was used. */ bool saw_opt_S = false; /* The first input file with an extension of .go. */ const char *first_go_file = NULL; argc = *in_decoded_options_count; decoded_options = *in_decoded_options; added_libraries = *in_added_libraries; args = XCNEWVEC (int, argc); for (i = 1; i < argc; i++) { const char *arg = decoded_options[i].arg; switch (decoded_options[i].opt_index) { case OPT_nostdlib: case OPT_nodefaultlibs: library = -1; break; case OPT_l: if (strcmp (arg, MATH_LIBRARY) == 0) { args[i] |= MATHLIB; need_math = 0; } else if (strcmp (arg, THREAD_LIBRARY) == 0) args[i] |= THREADLIB; else if (strcmp (arg, "c") == 0) args[i] |= WITHLIBC; else /* Unrecognized libraries (e.g. -lfoo) may require libgo. */ library = (library == 0) ? 1 : library; break; case OPT_pg: case OPT_p: saw_profile_flag = true; break; case OPT_x: if (library == 0 && strcmp (arg, "go") == 0) library = 1; break; case OPT_Xlinker: case OPT_Wl_: /* Arguments that go directly to the linker might be .o files, or something, and so might cause libgo to be needed. */ if (library == 0) library = 1; break; case OPT_c: case OPT_E: case OPT_M: case OPT_MM: case OPT_fsyntax_only: /* Don't specify libraries if we won't link, since that would cause a warning. */ saw_opt_c = true; library = -1; break; case OPT_S: saw_opt_S = true; library = -1; break; case OPT_o: saw_opt_o = true; break; case OPT_static: static_link = 1; break; case OPT_static_libgcc: shared_libgcc = 0; break; case OPT_static_libgo: library = library >= 0 ? 2 : library; args[i] |= SKIPOPT; break; case OPT_SPECIAL_input_file: if (library == 0) library = 1; if (first_go_file == NULL) { int len; len = strlen (arg); if (len > 3 && strcmp (arg + len - 3, ".go") == 0) first_go_file = arg; } break; } } /* There's no point adding -shared-libgcc if we don't have a shared libgcc. */ #ifndef ENABLE_SHARED_LIBGCC shared_libgcc = 0; #endif /* Make sure to have room for the trailing NULL argument. */ num_args = argc + need_math + shared_libgcc + (library > 0) * 5 + 10; new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args); i = 0; j = 0; /* Copy the 0th argument, i.e., the name of the program itself. */ new_decoded_options[j++] = decoded_options[i++]; /* If we are linking, pass -fsplit-stack if it is supported. */ #ifdef TARGET_CAN_SPLIT_STACK if (library >= 0) { generate_option (OPT_fsplit_stack, NULL, 1, CL_DRIVER, &new_decoded_options[j]); j++; } #endif /* NOTE: We start at 1 now, not 0. */ while (i < argc) { new_decoded_options[j] = decoded_options[i]; /* Make sure -lgo is before the math library, since libgo itself uses those math routines. */ if (!saw_math && (args[i] & MATHLIB) && library > 0) { --j; saw_math = &decoded_options[i]; } if (!saw_thread && (args[i] & THREADLIB) && library > 0) { --j; saw_thread = &decoded_options[i]; } if (!saw_libc && (args[i] & WITHLIBC) && library > 0) { --j; saw_libc = &decoded_options[i]; } if ((args[i] & SKIPOPT) != 0) --j; i++; j++; } /* If we didn't see a -o option, add one. This is because we need the driver to pass all .go files to go1. Without a -o option the driver will invoke go1 separately for each input file. FIXME: This should probably use some other interface to force the driver to set combine_inputs. */ if (first_go_file != NULL && !saw_opt_o) { if (saw_opt_c || saw_opt_S) { const char *base; int baselen; int alen; char *out; base = lbasename (first_go_file); baselen = strlen (base) - 3; alen = baselen + 3; out = XNEWVEC (char, alen); memcpy (out, base, baselen); /* The driver will convert .o to some other suffix (e.g., .obj) if appropriate. */ out[baselen] = '.'; if (saw_opt_S) out[baselen + 1] = 's'; else out[baselen + 1] = 'o'; out[baselen + 2] = '\0'; generate_option (OPT_o, out, 1, CL_DRIVER, &new_decoded_options[j]); } else generate_option (OPT_o, "a.out", 1, CL_DRIVER, &new_decoded_options[j]); j++; }
static char * make_relative_prefix_1 (const char *progname, const char *bin_prefix, const char *prefix, const int resolve_links) { char **prog_dirs = NULL, **bin_dirs = NULL, **prefix_dirs = NULL; int prog_num, bin_num, prefix_num; int i, n, common; int needed_len; char *ret = NULL, *ptr, *full_progname; if (progname == NULL || bin_prefix == NULL || prefix == NULL) return NULL; /* If there is no full pathname, try to find the program by checking in each of the directories specified in the PATH environment variable. */ if (lbasename (progname) == progname) { char *temp; #if 0 temp = getenv ("PATH"); if (temp) { char *startp, *endp, *nstore; size_t prefixlen = strlen (temp) + 1; size_t len; if (prefixlen < 2) prefixlen = 2; len = prefixlen + strlen (progname) + 1; #ifdef HAVE_HOST_EXECUTABLE_SUFFIX len += strlen (HOST_EXECUTABLE_SUFFIX); #endif nstore = (char *) alloca (len); startp = endp = temp; while (1) { if (*endp == PATH_SEPARATOR || *endp == 0) { if (endp == startp) { nstore[0] = '.'; nstore[1] = DIR_SEPARATOR; nstore[2] = '\0'; } else { memcpy (nstore, startp, endp - startp); if (! IS_DIR_SEPARATOR (endp[-1])) { nstore[endp - startp] = DIR_SEPARATOR; nstore[endp - startp + 1] = 0; } else nstore[endp - startp] = 0; } strcat (nstore, progname); if (! access (nstore, X_OK) #ifdef HAVE_HOST_EXECUTABLE_SUFFIX || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK) #endif ) { #if defined (HAVE_SYS_STAT_H) && defined (S_ISREG) struct stat st; if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode)) #endif { progname = nstore; break; } } if (*endp == 0) break; endp = startp = endp + 1; } else endp++; } } #endif } if (resolve_links) full_progname = lrealpath (progname); else full_progname = strdup (progname); if (full_progname == NULL) return NULL; prog_dirs = split_directories (full_progname, &prog_num); free (full_progname); if (prog_dirs == NULL) return NULL; bin_dirs = split_directories (bin_prefix, &bin_num); if (bin_dirs == NULL) goto bailout; /* Remove the program name from comparison of directory names. */ prog_num--; /* If we are still installed in the standard location, we don't need to specify relative directories. Also, if argv[0] still doesn't contain any directory specifiers after the search above, then there is not much we can do. */ if (prog_num == bin_num) { for (i = 0; i < bin_num; i++) { if (strcmp (prog_dirs[i], bin_dirs[i]) != 0) break; } if (prog_num <= 0 || i == bin_num) goto bailout; } prefix_dirs = split_directories (prefix, &prefix_num); if (prefix_dirs == NULL) goto bailout; /* Find how many directories are in common between bin_prefix & prefix. */ n = (prefix_num < bin_num) ? prefix_num : bin_num; for (common = 0; common < n; common++) { if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0) break; } /* If there are no common directories, there can be no relative prefix. */ if (common == 0) goto bailout; /* Two passes: first figure out the size of the result string, and then construct it. */ needed_len = 0; for (i = 0; i < prog_num; i++) needed_len += strlen (prog_dirs[i]); needed_len += sizeof (DIR_UP) * (bin_num - common); for (i = common; i < prefix_num; i++) needed_len += strlen (prefix_dirs[i]); needed_len += 1; /* Trailing NUL. */ ret = (char *) malloc (needed_len); if (ret == NULL) goto bailout; /* Build up the pathnames in argv[0]. */ *ret = '\0'; for (i = 0; i < prog_num; i++) strcat (ret, prog_dirs[i]); /* Now build up the ..'s. */ ptr = ret + strlen(ret); for (i = common; i < bin_num; i++) { strcpy (ptr, DIR_UP); ptr += sizeof (DIR_UP) - 1; *(ptr++) = DIR_SEPARATOR; } *ptr = '\0'; /* Put in directories to move over to prefix. */ for (i = common; i < prefix_num; i++) strcat (ret, prefix_dirs[i]); bailout: free_split_directories (prog_dirs); free_split_directories (bin_dirs); free_split_directories (prefix_dirs); return ret; }