⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldrdf.c

📁 nasm的全套源代码,有些我做了些修改,以方便您更方便更容易调试成功,方便学习做编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
                                (int)hr->r.segment, hr->r.offset);
                    *data = (char)offset;
                    break;
                case 2:
                    offset += *(short *)data;
                    if (offset < -32767 || offset > 32768)
                        fprintf(error_file,
                                "warning: relocation out of range "
                                "at %s(%02x:%08lx)\n", cur->name,
                                (int)hr->r.segment, hr->r.offset);
                    *(short *)data = (short)offset;
                    break;
                case 4:
                    *(long *)data += offset;
                    /* we can't easily detect overflow on this one */
                    break;
                }

                /*
                 * If the relocation was relative between two symbols in
                 * the same segment, then we're done.
                 *
                 * Otherwise, we need to output a new relocation record
                 * with the references updated segment and offset...
                 */
                if (!isrelative || cur->seginfo[localseg].dest_seg != seg) {
                    hr->r.segment = cur->seginfo[localseg].dest_seg;
                    hr->r.offset += cur->seginfo[localseg].reloc;
                    hr->r.refseg = seg;
                    if (isrelative)
                        hr->r.segment += RDOFF_RELATIVEMASK;
                    rdfaddheader(rdfheader, hr);
                }
                break;

            case RDFREC_IMPORT:        /* import symbol */
            case RDFREC_FARIMPORT:
                /*
                 * scan the global symbol table for the symbol
                 * and associate its location with the segment number 
                 * for this module
                 */
                se = symtabFind(symtab, hr->i.label);
                if (!se || se->segment == -1) {
                    if (!options.dynalink && !(hr->i.flags & SYM_IMPORT)) {
                        fprintf(error_file,
                                "error: unresolved reference to `%s'"
                                " in module `%s'\n", hr->i.label,
                                cur->name);
                        errorcount++;
                    }
                    /*
                     * we need to allocate a segment number for this
                     * symbol, and store it in the symbol table for
                     * future reference
                     */
                    if (!se) {
                        se = malloc(sizeof(*se));
                        if (!se) {
                            fprintf(stderr, "ldrdf: out of memory\n");
                            exit(1);
                        }
                        se->name = strdup(hr->i.label);
                        se->flags = 0;
                        se->segment = availableseg++;
                        se->offset = 0;
                        symtabInsert(symtab, se);
                    } else {
                        se->segment = availableseg++;
                        se->offset = 0;
                    }
                    /*
                     * output a header record that imports it to the
                     * recently allocated segment number...
                     */
                    newrec = *hr;
                    newrec.i.segment = se->segment;
                    rdfaddheader(rdfheader, &newrec);
                }

                add_seglocation(&segs, hr->i.segment, se->segment,
                                se->offset);
                break;

            case RDFREC_GLOBAL:        /* export symbol */
                /*
                 * need to insert an export for this symbol into the new
                 * header, unless we're stripping symbols. Even if we're
                 * stripping, put the symbol if it's marked as SYM_GLOBAL.
                 */
                if (options.strip && !(hr->e.flags & SYM_GLOBAL))
                    break;

                if (hr->e.segment == 2) {
                    seg = 2;
                    offset = cur->bss_reloc;
                } else {
                    localseg = rdffindsegment(&cur->f, hr->e.segment);
                    if (localseg == -1) {
                        fprintf(stderr, "%s: exported symbol `%s' from "
                                "unrecognised segment\n", cur->name,
                                hr->e.label);
                        errorcount++;
                        break;
                    }
                    offset = cur->seginfo[localseg].reloc;
                    seg = cur->seginfo[localseg].dest_seg;
                }

                hr->e.segment = seg;
                hr->e.offset += offset;
                rdfaddheader(rdfheader, hr);
                break;

            case RDFREC_MODNAME:       /* module name */
                /*
                 * Insert module name record if export symbols
                 * are not stripped.
                 * If module name begins with '$' - insert it anyway.
                 */
                if (options.strip && hr->m.modname[0] != '$')
                    break;
                rdfaddheader(rdfheader, hr);
                break;

            case RDFREC_DLL:   /* DLL name */
                /*
                 * Insert DLL name if it begins with '$'
                 */
                if (hr->d.libname[0] != '$')
                    break;
                rdfaddheader(rdfheader, hr);
                break;

            case RDFREC_SEGRELOC:      /* segment fixup */
                /*
                 * modify the segment numbers if necessary, and
                 * pass straight through to the output module header
                 *
                 * *** FIXME ***
                 */
                if (hr->r.segment == 2) {
                    fprintf(stderr, "%s: segment fixup in BSS section\n",
                            cur->name);
                    errorcount++;
                    break;
                }
                localseg = rdffindsegment(&cur->f, hr->r.segment);
                if (localseg == -1) {
                    fprintf(stderr, "%s: segment fixup in unrecognised"
                            " segment (%d)\n", cur->name, hr->r.segment);
                    errorcount++;
                    break;
                }
                hr->r.segment = cur->seginfo[localseg].dest_seg;
                hr->r.offset += cur->seginfo[localseg].reloc;

                if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset)) {
                    fprintf(stderr, "%s: segment fixup to undefined "
                            "segment %04x\n", cur->name,
                            (int)hr->r.refseg);
                    errorcount++;
                    break;
                }
                hr->r.refseg = seg;
                rdfaddheader(rdfheader, hr);
                break;

            case RDFREC_COMMON:        /* Common variable */
                /* Is this symbol already in the table? */
                se = symtabFind(symtab, hr->c.label);
                if (!se) {
                    printf("%s is not in symtab yet\n", hr->c.label);
                    break;
                }
                /* Add segment location */
                add_seglocation(&segs, hr->c.segment, se->segment,
                                se->offset);
                break;
            }
        }

        free(header);
        done_seglocations(&segs);

    }

    /*
     * combined BSS reservation for the entire results
     */
    newrec.type = RDFREC_BSS;
    newrec.b.reclen = 4;
    newrec.b.amount = bss_length;
    rdfaddheader(rdfheader, &newrec);

    /*
     * Write the header
     */
    for (i = 0; i < nsegs; i++) {
        if (i == 2)
            continue;
        rdfaddsegment(rdfheader, outputseg[i].length);
    }

    rdfwriteheader(f, rdfheader);
    rdfdoneheader(rdfheader);

    /*
     * Step through the segments, one at a time, writing out into
     * the output file
     */
    for (i = 0; i < nsegs; i++) {
        uint16 s;
        long l;

        if (i == 2)
            continue;

        s = translateshort(outputseg[i].type);
        fwrite(&s, 2, 1, f);
        s = translateshort(outputseg[i].number);
        fwrite(&s, 2, 1, f);
        s = translateshort(outputseg[i].reserved);
        fwrite(&s, 2, 1, f);
        l = translatelong(outputseg[i].length);
        fwrite(&l, 4, 1, f);

        fwrite(outputseg[i].data, outputseg[i].length, 1, f);
    }

    fwrite("\0\0\0\0\0\0\0\0\0\0", 10, 1, f);
}

/* =========================================================================
 * Main program
 */

void usage()
{
    printf("usage:\n"
           "   ldrdf [options] object modules ... [-llibrary ...]\n"
           "   ldrdf -r\n"
           "options:\n"
           "   -v[=n]          increase verbosity by 1, or set it to n\n"
           "   -a nn           set segment alignment value (default 16)\n"
           "   -s              strip public symbols\n"
           "   -dy             Unix-style dynamic linking\n"
           "   -o name         write output in file 'name'\n"
           "   -j path         specify objects search path\n"
           "   -L path         specify libraries search path\n"
           "   -g file         embed 'file' as a first header record with type 'generic'\n");
    exit(0);
}

int main(int argc, char **argv)
{
    char *outname = "aout.rdf";
    int moduleloaded = 0;
    char *respstrings[128] = { 0, };

    options.verbose = 0;
    options.align = 16;
    options.dynalink = 0;
    options.strip = 0;

    error_file = stderr;

    argc--, argv++;
    if (argc == 0)
        usage();
    while (argc && *argv && **argv == '-' && argv[0][1] != 'l') {
        switch (argv[0][1]) {
        case 'r':
            printf("ldrdf (linker for RDF files) version " LDRDF_VERSION
                   "\n");
            printf("RDOFF2 revision %s\n", RDOFF2_REVISION);
            exit(0);
        case 'v':
            if (argv[0][2] == '=') {
                options.verbose = argv[0][3] - '0';
                if (options.verbose < 0 || options.verbose > 9) {
                    fprintf(stderr,
                            "ldrdf: verbosity level must be a number"
                            " between 0 and 9\n");
                    exit(1);
                }
            } else
                options.verbose++;
            break;
        case 'a':
            options.align = atoi(argv[1]);
            if (options.align <= 0) {
                fprintf(stderr,
                        "ldrdf: -a expects a positive number argument\n");
                exit(1);
            }
            argv++, argc--;
            break;
        case 's':
            options.strip = 1;
            break;
        case 'd':
            if (argv[0][2] == 'y')
                options.dynalink = 1;
            break;
        case 'o':
            outname = argv[1];
            argv++, argc--;
            break;
        case 'j':
            if (!objpath) {
                options.objpath = 1;
                objpath = argv[1];
                argv++, argc--;
                break;
            } else {
                fprintf(stderr,
                        "ldrdf: more than one objects search path specified\n");
                exit(1);
            }
        case 'L':
            if (!libpath) {
                options.libpath = 1;
                libpath = argv[1];
                argv++, argc--;
                break;
            } else {
                fprintf(stderr,
                        "ldrdf: more than one libraries search path specified\n");
                exit(1);
            }
        case '@':{
                int i = 0;
                char buf[256];
                FILE *f;

                options.respfile = 1;
                if (argv[1] != NULL)
                    f = fopen(argv[1], "r");
                else {
                    fprintf(stderr,
                            "ldrdf: no response file name specified\n");
                    exit(1);
                }

                if (f == NULL) {
                    fprintf(stderr,
                            "ldrdf: unable to open response file\n");
                    exit(1);
                }

                argv++, argc--;
                while (fgets(buf, sizeof(buf), f) != NULL) {
                    char *p;
                    if (buf[0] == '\n')
                        continue;
                    if ((p = strchr(buf, '\n')) != NULL)
                        *p = '\0';
                    if (i >= 128) {
                        fprintf(stderr, "ldrdf: too many input files\n");
                        exit(1);
                    }
                    *(respstrings + i) = newstr(buf);
                    argc++, i++;
                }
                break;
            }
        case '2':
            options.stderr_redir = 1;
            error_file = stdout;
            break;
        case 'g':
            generic_rec_file = argv[1];
            argv++, argc--;
            break;
        default:
            usage();
        }
        argv++, argc--;
    }

    if (options.verbose > 4) {
        printf("ldrdf invoked with options:\n");
        printf("    section alignment: %d bytes\n", options.align);
        printf("    output name: `%s'\n", outname);
        if (options.strip)
            printf("    strip symbols\n");
        if (options.dynalink)
            printf("    Unix-style dynamic linking\n");
        if (options.objpath)
            printf("    objects search path: %s\n", objpath);
        if (options.libpath)
            printf("    libraries search path: %s\n", libpath);
        printf("\n");
    }

    symtab = symtabNew();
    initsegments();

    if (!symtab) {
        fprintf(stderr, "ldrdf: out of memory\n");
        exit(1);
    }

    while (argc) {
        if (!*argv)
            argv = respstrings;
        if (!*argv)
            break;
        if (!strncmp(*argv, "-l", 2)) {
            if (libpath && (argv[0][2] != '/'))
                add_library(newstrcat(libpath, *argv + 2));
            else
                add_library(*argv + 2);
        } else {
            if (objpath && (argv[0][0] != '/'))
                loadmodule(newstrcat(objpath, *argv));
            else
                loadmodule(*argv);
            moduleloaded = 1;
        }
        argv++, argc--;
    }

    if (!moduleloaded) {
        printf("ldrdf: nothing to do. ldrdf -h for usage\n");
        return 0;
    }

    search_libraries();

    if (options.verbose > 2) {
        printf("symbol table:\n");
        symtabDump(symtab, stdout);
    }

    write_output(outname);

    if (errorcount > 0)
        exit(1);
    return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -