summary refs log tree commit diff stats
path: root/tinyc/c67-link.c
blob: de72e442f85b3b3c7bcae3d9e2e242e32952cf34 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#ifdef TARGET_DEFS_ONLY

#define EM_TCC_TARGET EM_C60

/* relocation type for 32 bit data relocation */
#define R_DATA_32   R_C60_32
#define R_DATA_PTR  R_C60_32
#define R_JMP_SLOT  R_C60_JMP_SLOT
#define R_GLOB_DAT  R_C60_GLOB_DAT
#define R_COPY      R_C60_COPY
#define R_RELATIVE  R_C60_RELATIVE

#define R_NUM       R_C60_NUM

#define ELF_START_ADDR 0x00000400
#define ELF_PAGE_SIZE  0x1000

#define PCRELATIVE_DLLPLT 0
#define RELOCATE_DLLPLT 0

#else /* !TARGET_DEFS_ONLY */

#include "tcc.h"

/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
   relocations, returns -1. */
int code_reloc (int reloc_type)
{
    switch (reloc_type) {
        case R_C60_32:
	case R_C60LO16:
	case R_C60HI16:
        case R_C60_GOT32:
        case R_C60_GOTOFF:
        case R_C60_GOTPC:
        case R_C60_COPY:
            return 0;

        case R_C60_PLT32:
            return 1;
    }

    tcc_error ("Unknown relocation type: %d", reloc_type);
    return -1;
}

/* Returns an enumerator to describe whether and when the relocation needs a
   GOT and/or PLT entry to be created. See tcc.h for a description of the
   different values. */
int gotplt_entry_type (int reloc_type)
{
    switch (reloc_type) {
        case R_C60_32:
	case R_C60LO16:
	case R_C60HI16:
        case R_C60_COPY:
            return NO_GOTPLT_ENTRY;

        case R_C60_GOTOFF:
        case R_C60_GOTPC:
            return BUILD_GOT_ONLY;

        case R_C60_PLT32:
        case R_C60_GOT32:
            return ALWAYS_GOTPLT_ENTRY;
    }

    tcc_error ("Unknown relocation type: %d", reloc_type);
    return -1;
}

ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
    tcc_error("C67 got not implemented");
    return 0;
}

/* relocate the PLT: compute addresses and offsets in the PLT now that final
   address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *s1)
{
    uint8_t *p, *p_end;

    if (!s1->plt)
      return;

    p = s1->plt->data;
    p_end = p + s1->plt->data_offset;

    if (p < p_end) {
        /* XXX: TODO */
        while (p < p_end) {
            /* XXX: TODO */
        }
   }
}

void relocate_init(Section *sr) {}

void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
{
    switch(type) {
        case R_C60_32:
            *(int *)ptr += val;
            break;
        case R_C60LO16:
            {
                uint32_t orig;

                /* put the low 16 bits of the absolute address add to what is
                   already there */
                orig  =   ((*(int *)(ptr  )) >> 7) & 0xffff;
                orig |=  (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;

                /* patch both at once - assumes always in pairs Low - High */
                *(int *) ptr    = (*(int *) ptr    & (~(0xffff << 7)) ) |
                                   (((val+orig)      & 0xffff) << 7);
                *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) |
                                  ((((val+orig)>>16) & 0xffff) << 7);
            }
            break;
        case R_C60HI16:
            break;
        default:
            fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
                    type, (unsigned) addr, ptr, (unsigned) val);
            break;
    }
}

#endif /* !TARGET_DEFS_ONLY */
class="w"> attempt(dir / "src" / pkg / f) p = parentDir(p) when considerNimbleDirs: if not options.gNoNimblePath: var nimbleDir = getEnv("NIMBLE_DIR") if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble" result = findInNimbleDir(pkg, subdir, nimbleDir / "pkgs") if result.len > 0: return result when not defined(windows): result = findInNimbleDir(pkg, subdir, "/opt/nimble/pkgs") if result.len > 0: return result proc scriptableImport(pkg, sub: string; info: TLineInfo): string = resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info) proc lookupPackage(pkg, subdir: PNode): string = let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: "" case pkg.kind of nkStrLit, nkRStrLit, nkTripleStrLit: result = scriptableImport(pkg.strVal, sub, pkg.info) of nkIdent: result = scriptableImport(pkg.ident.s, sub, pkg.info) else: localError(pkg.info, "package name must be an identifier or string literal") result = "" proc getModuleName*(conf: ConfigRef; n: PNode): string = # This returns a short relative module name without the nim extension # e.g. like "system", "importer" or "somepath/module" # The proc won't perform any checks that the path is actually valid case n.kind of nkStrLit, nkRStrLit, nkTripleStrLit: try: result = pathSubs(conf, n.strVal, toFullPath(conf, n.info).splitFile().dir) except ValueError: localError(conf, n.info, "invalid path: " & n.strVal) result = n.strVal of nkIdent: result = n.ident.s of nkSym: result = n.sym.name.s of nkInfix: let n0 = n[0] let n1 = n[1] when false: if n1.kind == nkPrefix and n1[0].kind == nkIdent and n1[0].ident.s == "$": if n0.kind == nkIdent and n0.ident.s == "/": result = lookupPackage(n1[1], n[2]) else: localError(n.info, "only '/' supported with $package notation") result = "" else: let modname = getModuleName(conf, n[2]) # hacky way to implement 'x / y /../ z': result = getModuleName(conf, n1) result.add renderTree(n0, {renderNoComments}).replace(" ") result.add modname of nkPrefix: when false: if n[0].kind == nkIdent and n[0].ident.s == "$": result = lookupPackage(n[1], nil) else: discard # hacky way to implement 'x / y /../ z': result = renderTree(n, {renderNoComments}).replace(" ") of nkDotExpr: localError(conf, n.info, warnDeprecated, "using '.' instead of '/' in import paths is deprecated") result = renderTree(n, {renderNoComments}).replace(".", "/") of nkImportAs: result = getModuleName(conf, n[0]) else: localError(conf, n.info, "invalid module name: '$1'" % n.renderTree) result = "" proc checkModuleName*(conf: ConfigRef; n: PNode; doLocalError=true): FileIndex = # This returns the full canonical path for a given module import let modulename = getModuleName(conf, n) let fullPath = findModule(conf, modulename, toFullPath(conf, n.info)) if fullPath.isEmpty: if doLocalError: let m = if modulename.len > 0: modulename else: $n localError(conf, n.info, "cannot open file: " & m) result = InvalidFileIdx else: result = fileInfoIdx(conf, fullPath)