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); } }
/* * 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; }
/* * 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; }
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; } }
/* * 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; }
/* * 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; }
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)); }
/* * 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); }
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; }
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); }
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); }
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)); }