# This shell script emits a C file. -*- C -*- # It does some substitutions. # Derived from generic.em and partialy from emx's ld.c cat >e${EMULATION_NAME}.c <>e${EMULATION_NAME}.c <> e${EMULATION_NAME}.c #echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c #sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c #echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c #sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c #echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c #sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c #echo ' ; else return' >> e${EMULATION_NAME}.c #sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c #echo '; }' >> e${EMULATION_NAME}.c cat >>e${EMULATION_NAME}.c <> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c echo ' ; else return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c echo '; }' >> e${EMULATION_NAME}.c else # Scripts read from the filesystem. cat >>e${EMULATION_NAME}.c <>e${EMULATION_NAME}.c < #include #include #include /* bird: clash with abort macro in ld should really include this earlier * Quick fix is to undefine the abort macro. */ #undef abort #include #define abort() ld_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__) /* bird: include headers for alloca and utime too please */ #include #include static const char *exe_filename; static const char *def_filename = NULL; static const char *res_filename = NULL; static const char *map_filename = NULL; static const char *touch_filename = NULL; static int reloc_flag = 0; static int dll_flag = 0; static int exe_flag = 0; static int map_flag = 0; static int stack_size = 0; static int emxbind_strip = 0; enum exe_bind_type { EMX_DEFAULT, RSXNT_WIN32, RSXNT_RSX, RSXNT_EMX } rsxnt_linked = EMX_DEFAULT; int gld_${EMULATION_NAME}_parse_args (argc, argv) int argc; char **argv; { int longind; int optc; int prevoptind = optind; int prevopterr = opterr; opterr = 0; optc = getopt_long_only (argc, argv, "-", longopts, &longind); opterr = prevopterr; switch (optc) { default: optind = prevoptind; return 0; case OPT_ZEXE: exe_flag = 1; break; case OPT_ZSTACK: stack_size = parse (optarg, "%i", "invalid argument '%s' to -Zstack"); break; case OPT_ZMAP: map_flag = 1; map_filename = optarg; break; case OPT_ZNODEMANGLE: fatal ("-Znodemangle not implemented yet"); break; case OPT_ZDEMANGLEPROTO: fatal ("-Zdemangle-proto not implemented yet"); break; case OPT_ZEMX32: rsxnt_linked = RSXNT_EMX; break; case OPT_ZRSX32: rsxnt_linked = RSXNT_RSX; break; case OPT_ZWIN32: rsxnt_linked = RSXNT_WIN32; break; } return 1; } /* * This routine is used to post-process command-line options, * since after_parse hook is invoked too late for us (changing * output_filename is not effective). */ void gld${EMULATION_NAME}_set_symbols () { char *ext, *tmp_dir, *tmp; size_t tmp_dir_len; if (rsxnt_linked != EMX_DEFAULT && link_info.strip != strip_none) /* RSXNT */ { /* rsxnt can't live without all (even debugging) symbols??? */ link_info.strip = strip_none; emxbind_strip = 1; } else if (link_info.strip != strip_none) { /* emxbind cant live without extern defs... */ link_info.strip = strip_debugger; emxbind_strip = 1; } /* Always generate relocatable output since ld is just the first stage ... */ link_info.relocateable = true; if (exe_flag) { ext = _getext (output_filename); if ((ext != NULL) && (stricmp (ext, ".exe") == 0)) { exe_filename = output_filename; exe_flag = 0; } else { touch_filename = strdup(output_filename); exe_filename = concat (output_filename, ".exe", NULL); } } else { ext = _getext2 (output_filename); if (stricmp (ext, ".dll") == 0) { link_info.relocateable = true; dll_flag = 1; } else if (stricmp (ext, ".exe") != 0) { exe_filename = NULL; return; } exe_filename = output_filename; } /* Create a temporary a.out executable file. */ tmp_dir = getenv ("TMPDIR"); if (tmp_dir == NULL) tmp_dir = getenv ("TMP"); if (tmp_dir == NULL) tmp_dir = getenv ("TEMP"); if (tmp_dir == NULL) tmp_dir = "."; tmp_dir_len = strlen (tmp_dir); output_filename = tmp = xmalloc (tmp_dir_len + 10); memcpy (tmp, tmp_dir, tmp_dir_len); if (tmp_dir_len != 0 && strchr ("\\\\/:", tmp_dir[tmp_dir_len-1]) == NULL) tmp[tmp_dir_len++] = '\\\\'; strcpy (tmp + tmp_dir_len, "ldXXXXXX"); if (mktemp (tmp) == NULL) fatal ("mktemp(\\"%s\\") failed", output_filename); unlink (exe_filename); if (touch_filename != NULL) unlink (touch_filename); } boolean gld_${EMULATION_NAME}_unrecognized_file (entry) lang_input_statement_type *entry; { char *ext; ext = _getext (entry->filename); if (ext != NULL) { if (stricmp (ext, ".def") == 0) { def_filename = entry->filename; entry->loaded = true; return true; } else if (stricmp (ext, ".res") == 0) { res_filename = entry->filename; entry->loaded = true; return true; } } return false; } extern u_int DosCopy (char *pszSource, char *pszTarget, u_int ulOption); /* Perform final action(s) on output file */ void gld_${EMULATION_NAME}_finish_link (char *filename) { struct stat statbuf; int filemode, mask; if (stat (output_filename, &statbuf) < 0) fatal ("cannot query file status for %s\\n", output_filename); filemode = statbuf.st_mode; mask = umask (0); umask (mask); if (rsxnt_linked == EMX_DEFAULT && exe_filename) { char *nargv[11]; int i, saved_errno; i = 0; nargv[i++] = "emxbind"; nargv[i++] = "-bq"; if (emxbind_strip) nargv[i++] = "-s"; if (def_filename) { nargv[i] = alloca (strlen (def_filename) + 3); strcpy (nargv[i], "-d"); strcat (nargv[i], def_filename); i++; } else if (dll_flag) nargv[i++] = "-d"; if (stack_size != 0) { nargv[i] = alloca (20); sprintf (nargv[i], "-k0x%x", stack_size); i++; } if (map_flag) { if (map_filename == NULL) { map_filename = alloca (strlen (exe_filename) + 5); strcpy ((char *)map_filename, exe_filename); _remext ((char *)map_filename); strcat ((char *)map_filename, ".map"); } nargv[i] = alloca (strlen (map_filename) + 3); strcpy (nargv[i], "-m"); strcat (nargv[i], map_filename); i++; } if (res_filename) { nargv[i] = alloca (strlen (res_filename) + 3); strcpy (nargv[i], "-r"); strcat (nargv[i], res_filename); i++; } nargv[i++] = "-o"; nargv[i++] = (char *)exe_filename; nargv[i++] = (char *)output_filename; nargv[i] = NULL; i = spawnvp (P_WAIT, "emxbind", nargv); saved_errno = errno; unlink (output_filename); errno = saved_errno; if (i < 0) fatal ("failed to run emxbind\\n", NULL); else if (i != 0) fatal ("emxbind failed\\n", NULL); if (chmod (exe_filename, filemode | (0111 & ~mask)) == -1) fatal ("failed to write file %s\\n", exe_filename); if (touch_filename) { char execname[512]; _execname(execname, sizeof(execname)); strcpy(_getname(execname), "ldstub.bin"); /* Copy stub into file */ if (DosCopy(execname, (char *)touch_filename, 4)) fatal ("cannot copy %s to %s\\n", execname, touch_filename); /* Now touch it */ if (utime (touch_filename, NULL)) fatal ("cannot touch file %s\\n", touch_filename); } } else if (exe_filename) /* RSXNT */ { char *nargv[10]; int i, saved_errno; i = 0; nargv[i++] = "ntbind"; if (emxbind_strip) nargv[i++] = "-s"; nargv[i++] = "-o"; nargv[i++] = (char *)exe_filename; nargv[i++] = (char *)output_filename; if (rsxnt_linked == RSXNT_WIN32) nargv[i++] = (emxbind_strip) ? "dosstub.dos" : "dosstub.dbg"; else { nargv[i++] = "dosstub.rsx"; if (emxbind_strip) nargv[i++] = "-strip"; } if (def_filename) { nargv[i++] = "-d"; nargv[i] = alloca (strlen (def_filename) + 3); strcpy(nargv[i], def_filename); i++; } nargv[i] = NULL; i = spawnvp (P_WAIT, "ntbind", nargv); saved_errno = errno; unlink (output_filename); errno = saved_errno; if (i < 0) fatal ("failed to run ntbind\\n", NULL); else if (i != 0) fatal ("ntbind failed\\n", NULL); if (chmod (exe_filename, filemode | (0111 & ~mask)) == -1) fatal ("failed to write file %s\\n", exe_filename); if (touch_filename) { i = open (touch_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); if (i < 0) fatal ("failed to touch file %s\\n", touch_filename); close (i); } } } /* Create any output sections needed by the target. */ void gld${EMULATION_NAME}_create_output_section_statements (void) { /* Since we enabled relocations LD marked output file as non-pageable */ /* However, this is not true for emx: always generate paged output */ output_bfd->flags |= D_PAGED; } struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = { gld${EMULATION_NAME}_before_parse, syslib_default, hll_default, after_parse_default, after_open_default, after_allocation_default, set_output_arch_default, ldemul_default_target, before_allocation_default, gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", NULL, /* finish */ gld${EMULATION_NAME}_create_output_section_statements, /* create output section statements */ NULL, /* open dynamic archive */ NULL, /* place orphan */ gld${EMULATION_NAME}_set_symbols, /* set symbols */ gld_${EMULATION_NAME}_parse_args, gld_${EMULATION_NAME}_unrecognized_file, NULL, /* list_options */ NULL, /* recognized_file */ NULL, /* find_potential_libraries */ gld_${EMULATION_NAME}_finish_link }; EOF