Exemple #1
0
static void add_reloc(Elf *elf) {
    char name[100];
    for (int i = 0; i < LIST_LEN(elf->sections); i++) {
        Section *sect = LIST_REF(elf->sections, i);
        if (LIST_LEN(sect->rels) == 0)
            continue;
        String *b = make_string();
        for (int j = 0; j < LIST_LEN(sect->rels); j++) {
            Reloc *rel = LIST_REF(sect->rels, j);
            o8(b, rel->off);
            if (rel->sym) {
                o8(b, ELF64_R_INFO(find_symbol(elf, rel->sym)->index, rel->type));
            } else {
                o8(b, ELF64_R_INFO(rel->section->symindex, rel->type));
            }
            o8(b, rel->addend);
        }

        strcpy(name, ".rela");
        strcpy(name + 5, sect->name);
        Section *relsec = make_section(name, SHT_RELA);
        relsec->link = elf->symtabnum;
        relsec->info = i + 1;
        relsec->body = b;
        relsec->entsize = 24;
        relsec->align = 4;
        add_section(elf, relsec);
    }
}
Exemple #2
0
/*
 * Join tokens in a given list.  If sep is true, a space is put
 * between tokens.  If false, no separator.
 */
static String *join_tokens(List *arg, bool sep) {
    String *s = make_string();
    for (int i = 0; i < LIST_LEN(arg); i++) {
        Token *tok = LIST_REF(arg, i);
        if (sep && STRING_LEN(s) && tok->space)
            o1(s, ' ');
        switch (tok->toktype) {
        case TOKTYPE_IDENT:
        case TOKTYPE_CPPNUM:
            string_append(s, STRING_BODY(tok->val.str));
            break;
        case TOKTYPE_PUNCT:
            string_append(s, token_to_string(tok));
            break;
        case TOKTYPE_CHAR: {
            // TODO: retain original spelling
            o1(s, '\'');
            stringize_char(s, tok->val.i, '\'');
            string_append(s, "\'");
            break;
        }
        case TOKTYPE_STRING: {
            o1(s, '"');
            for (char *p = STRING_BODY(tok->val.str); *p; p++)
                stringize_char(s, *p, '\"');
            string_append(s, "\"");
            break;
        }
        default:
            panic("invalid token type: %d", tok->toktype);
        }
    }
    return s;
}
Exemple #3
0
/*
 * Reads macro arguments.  If the number of macro arguments does not match with
 * the number of parameters, it will raise an error.
 */
static List *read_args(CppContext *ctx, Macro *macro) {
    List *args = read_args_int(ctx, macro);
    if (!args) return NULL;

    /*
     * In CPP syntax, we cannot distinguish zero-argument macro invocation from
     * one argument macro invocation, because macro argument can be blank.  For
     * example, the following macro invocation
     *
     *   FOO()
     *
     * is valid for both definitions shown below.
     *
     *   #define FOO()  1
     *   #define FOO(x) x
     *
     * In the latter case, macro parameter "x" become an empty sequence of
     * identifiers, thus FOO() will be replaced with the empty.
     *
     * The argument list is set to empty here if macro takes no parameters and
     * the argument is empty.
     */
    if (macro->nargs == 0 && LIST_LEN(args) == 1 && LIST_LEN((List *)LIST_REF(args, 0)) == 0)
        list_pop(args);

    if ((macro->is_varg && LIST_LEN(args) < macro->nargs)
        || (!macro->is_varg && LIST_LEN(args) != macro->nargs))
        error_cpp_ctx(ctx, "Macro argument number does not match");
    return args;
}
Exemple #4
0
static void write_section_sym(Elf *elf, int *index, String *symtab, String *strtab) {
    for (int i = 0; i < LIST_LEN(elf->sections); i++) {
        Section *sect = LIST_REF(elf->sections, i);
        Symbol *sym = make_symbol(NULL, sect, 0, STB_LOCAL, STT_SECTION, 1);
        write_one_symbol(sym, index, symtab, strtab);
        sect->symindex = sym->index;
    }
}
Exemple #5
0
/*
 * Evaluate a given tokens as an integer constant expression and returns the
 * result.
 */
static int eval_const_expr(CppContext *cppctx, List *tokens) {
    if (LIST_LEN(tokens) == 1 && ((Token *)LIST_REF(tokens, 0))->toktype == TOKTYPE_CPPNUM)
        return ((Token *)LIST_REF(tokens, 0))->val.i;

    CppContext *virt = make_virt_cpp_context(cppctx, tokens);
    ReadContext *readctx = make_read_context(cppctx->file, NULL, virt);
    readctx->in_const_expr = true;
    Var *var = read_comma_expr(readctx);

    Token *tok = read_token(readctx);
    if (tok)
        error_token(tok, "newline expected, but got '%s'", token_to_string(tok));

    ASSERT(var->stype == VAR_IMM);
    if (!ctype_equal(var->ctype, CTYPE_INT))
        error_cpp_ctx(cppctx, "integer expected");
    return var->val.i;
}
Exemple #6
0
/*
 * Added a given hide set to tokens in a given list.
 */
static List *add_hide_set(List *tokens, List *hideset) {
    List *r = make_list();
    for (int i = 0; i < LIST_LEN(tokens); i++) {
        Token *t = copy_token((Token *)LIST_REF(tokens, i));
        t->hideset = list_union(t->hideset, hideset);
        list_push(r, t);
    }
    return r;
}
Exemple #7
0
static File *open_header(CppContext *ctx, String *name, List *paths) {
    for (int i = 0; i < LIST_LEN(paths); i++) {
        String *path = construct_path((String *)LIST_REF(paths, i), name);
        FILE *stream = fopen(STRING_BODY(path), "r");
        if (!stream)
            continue;
        return make_file(stream, STRING_BODY(path));
    }
    error_cpp_ctx(ctx, "Cannot find header: '%s'", STRING_BODY(name));
}
Exemple #8
0
/*
 * Substitutes parameters in macro definition body with actual arguments.
 */
static List *subst(CppContext *ctx, Macro *macro, List *args, List *hideset) {
    List *r = make_list();
    for (int i = 0; i < LIST_LEN(macro->body); i++) {
        bool islast = (i == LIST_LEN(macro->body) - 1);
        Token *t0 = LIST_REF(macro->body, i);
        Token *t1 = islast ? NULL : LIST_REF(macro->body, i + 1);
        bool t0_param = t0->toktype == TOKTYPE_MACRO_PARAM;
        bool t1_param = !islast && t1->toktype == TOKTYPE_MACRO_PARAM;

        if (is_punct(t0, '#') && t1_param) {
            list_push(r, stringize(t0, LIST_REF(args, t1->val.i)));
            i++;
            continue;
        }
        if (is_punct(t0, KEYWORD_TWOSHARPS) && t1_param) {
            List *arg = LIST_REF(args, t1->val.i);
            if (!LIST_IS_EMPTY(arg)) {
                glue_push(r, (Token *)LIST_REF(arg, 0));
                List *tmp = make_list();
                for (int i = 1; i < LIST_LEN(arg); i++)
                    list_push(tmp, LIST_REF(arg, i));
                list_append(r, expand_all(ctx, tmp));
            }
            i++;
            continue;
        }
        if (is_punct(t0, KEYWORD_TWOSHARPS) && !islast) {
            hideset = t1->hideset; // wrong?
            glue_push(r, t1);
            i++;
            continue;
        }
        if (t0_param && !islast && is_punct(t1, KEYWORD_TWOSHARPS)) {
            hideset = t1->hideset; // wrong?
            List *arg = LIST_REF(args, t0->val.i);
            if (LIST_IS_EMPTY(arg))
                i++;
            else
                list_append(r, arg);
            continue;
        }
        if (t0_param) {
            List *arg = LIST_REF(args, t0->val.i);
            list_append(r, expand_all(ctx, arg));
            continue;
        }
        list_push(r, t0);
    }
    return add_hide_set(r, hideset);
}
Exemple #9
0
static void add_shstrtab(Elf *elf) {
    Section *shstr = make_section(".shstrtab", SHT_STRTAB);
    elf->shnum = LIST_LEN(elf->sections) + 1;
    add_section(elf, shstr);
    String *b = make_string();
    o1(b, 0);
    for (int i = 0; i < LIST_LEN(elf->sections); i++) {
        Section *sect = LIST_REF(elf->sections, i);
        sect->shstrtab_off = STRING_LEN(b);
        ostr(b, sect->name);
    }
    shstr->body = b;
}
Exemple #10
0
elem XmlRpc_EncodeDate(elem obj)
{
	char buf[18];
	int i, a[6];
	elem t;

	for(i=0; i<6; i++)a[i]=TOINT(LIST_REF(obj, i+1));
	sprintf(buf, "%04d%02d%02dT%02d:%02d:%02d",
		a[0], a[1], a[2], a[3], a[4], a[5]);

	t=STRING(buf);
	t=CONS(t, MISC_EOL);
	t=CONS(MISC_EOL, t);
	t=CONS(SYM("dateTime.iso8601"), t);
	return(t);
}
Exemple #11
0
void write_elf(FILE *outfile, Elf *elf) {
    add_symtab(elf);
    add_reloc(elf);
    add_shstrtab(elf);

    // Section header
    String *sh = make_string();
    for (int i = 0; i < 64; i++)
        o1(sh, 0); // NULL section header

    // Body
    String *content = make_string();
    for (int i = 0; i < LIST_LEN(elf->sections); i++) {
        write_section(sh, content, LIST_REF(elf->sections, i), 64);
    }
    align(content, 16);

    // ELF header
    String *eh = make_string();
    int numsect = LIST_LEN(elf->sections) + 1;
    out(eh, elf_ident, sizeof(elf_ident));
    o2(eh, 1);  // e_type = ET_REL
    o2(eh, 62); // e_machine = EM_X86_64
    o4(eh, 1);  // e_version = EV_CURRENT
    o8(eh, 0);  // e_entry
    o8(eh, 0);  // e_phoff
    o8(eh, STRING_LEN(content) + 64);  // e_shoff;
    o4(eh, 0);  // e_flags
    o2(eh, 64); // e_ehsize
    o2(eh, 0);  // e_phentsize
    o2(eh, 0);  // e_phnum
    o2(eh, 64); // e_shentsize
    o2(eh, numsect);  // e_shnum
    o2(eh, elf->shnum);  // e_shstrndx

    fwrite(STRING_BODY(eh), STRING_LEN(eh), 1, outfile);
    fwrite(STRING_BODY(content), STRING_LEN(content), 1, outfile);
    fwrite(STRING_BODY(sh), STRING_LEN(sh), 1, outfile);
    fclose(outfile);
}
Exemple #12
0
static void pushback(CppContext *ctx, List *ts) {
    for (int i = LIST_LEN(ts) - 1; i >= 0; i--)
        unget_cpp_token(ctx, (Token *)LIST_REF(ts, i));
}