summaryrefslogtreecommitdiff
path: root/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c
blob: 4a2976a6bc1c73259ae22c758dd77f65ff27b3e3 (plain)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
/*
 * Copyright (C) ST-Ericsson SA 2010
 * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson.
 * License terms: GNU General Public License (GPL) version 2.
 */
#include <cm/engine/elf/inc/mpcal.h>

#include <cm/engine/utils/inc/string.h>
#include <cm/engine/utils/inc/mem.h>


static t_uint32 max(t_uint32 a, t_uint32 b)
{
    return (a >= b) ? a : b;
}
/*
static t_uint32 min(t_uint32 a, t_uint32 b)
{
    return (a <= b) ? a : b;
}
*/

struct XXrelocation
{
    t_uint32            st_value;
    ElfXX_Half          st_shndx;
    Elf64_Sxword        r_addend;
    t_uint32            OffsetInElf;
    t_uint32            type;

    t_dup_char          symbol_name;    // Valid only if st_shndx == SHN_UNDEF
};

struct XXSection {
    ElfXX_Word      sh_type;        /* Section type */
    t_uint32        sh_size;        /* Section size in bytes */
    ElfXX_Word      sh_info;        /* Additional section information */
    ElfXX_Word      sh_link;        /* Link to another section */
    t_uint32        sh_addralign;   /* Some sections have address alignment constraints */
    t_uint32        sh_addr;        /* Section addr */
    ElfXX_Xword     sh_flags;       /* Section flags */

    const char      *data;
    t_uint32        trueDataSize;   /* Valid if different from sh_size */
    const char      *sectionName;

    t_uint32            offsetInSegment;
    const t_elfmemory   *meminfo;

    t_uint32                relocationNumber;
    struct XXrelocation     *relocations;
};

struct XXElf {
    t_uint32            e_shnum;
    struct XXSection                sectionss[1];
};

t_cm_error ELF64_LoadComponent(
        t_uint16                    e_machine,
        const char                  *elfdata,
        t_elfdescription            **elfhandlePtr,
        t_tmp_elfdescription        *elftmp)
{
    t_elfdescription *elfhandle;
    const ElfXX_Ehdr *header = (ElfXX_Ehdr*)elfdata;
    const ElfXX_Shdr *sections;
    const char *strings;
    struct XXElf* ELF;
    int i, nb;

    elftmp->elfdata = elfdata;

    /* Sanity check */
    if (swapHalf(header->e_machine) != e_machine)
    {
        ERROR("This is not a executable for such MPC\n", 0, 0, 0, 0, 0, 0);
        return CM_INVALID_ELF_FILE;
    }

    // Cache elf file informations
    nb = swapHalf(header->e_shnum);
    elftmp->isExecutable = (swapHalf(header->e_type) == ET_EXEC);

    elfhandle = (t_elfdescription*)OSAL_Alloc_Zero(
            sizeof(t_elfdescription) + sizeof(struct XXElf) + sizeof(struct XXSection) * (nb - 1));
    if(elfhandle == NULL)
        return CM_NO_MORE_MEMORY;

    ELF = elfhandle->ELF = (struct XXElf*)(elfhandle + 1);

    ELF->e_shnum = nb;

    sections = (ElfXX_Shdr*)&elfdata[swapXword(header->e_shoff)];
    // Compute and swap section infromation
    for(i = 0; i < ELF->e_shnum; i++)
    {
        ELF->sectionss[i].sh_type = swapWord(sections[i].sh_type);
        ELF->sectionss[i].sh_info = swapWord(sections[i].sh_info);
        ELF->sectionss[i].sh_link = swapWord(sections[i].sh_link);
        ELF->sectionss[i].sh_size = (t_uint32)swapXword(sections[i].sh_size);
        ELF->sectionss[i].sh_addralign = (t_uint32)swapXword(sections[i].sh_addralign);
        ELF->sectionss[i].sh_addr = (t_uint32)swapXword(sections[i].sh_addr);
        ELF->sectionss[i].sh_flags = swapXword(sections[i].sh_flags);

        elftmp->sectionData[i] = &elfdata[(t_uint32)swapXword(sections[i].sh_offset)];
    }

    /*
     * search nmf_segment
     */
    strings = elftmp->sectionData[swapHalf(header->e_shstrndx)];
    for(i = 0; i < ELF->e_shnum; i++)
    {
        ELF->sectionss[i].sectionName = &strings[swapWord(sections[i].sh_name)];

        // Found nmf_segment to see if it's
        if(cm_StringCompare("nmf_segment", ELF->sectionss[i].sectionName, 11) == 0) {
            elftmp->nmfSectionIndex = i;
            elftmp->elfheader = (const t_elf_component_header*)elftmp->sectionData[i];
        }
    }

    if(elftmp->nmfSectionIndex == 0)
    {
        ERROR("This is not a NMF component\n", 0, 0, 0, 0, 0, 0);
        goto invalid;
    }

    /*
     * Determine component type
     */
    elfhandle->magicNumber = swap32(elftmp->elfheader->magic);
    switch(elfhandle->magicNumber) {
    case MAGIC_COMPONENT:
        elfhandle->instanceProperty = MEM_FOR_MULTIINSTANCE;
        break;
    case MAGIC_SINGLETON:
    case MAGIC_FIRMWARE:
        elfhandle->instanceProperty = MEM_FOR_SINGLETON;
        break;
    }

    // Copy content
    for(i = 0; i < ELF->e_shnum; i++)
    {
        ELF->sectionss[i].meminfo = MMDSP_getMappingByName(
                ELF->sectionss[i].sectionName,
                elfhandle->instanceProperty);

        if(ELF->sectionss[i].meminfo != NULL)
            ELF->sectionss[i].trueDataSize = (ELF->sectionss[i].sh_size / ELF->sectionss[i].meminfo->fileEntSize) * ELF->sectionss[i].meminfo->memEntSize;

        if(ELF->sectionss[i].sh_size != 0 &&
                ELF->sectionss[i].sh_type == SHT_PROGBITS &&
                (ELF->sectionss[i].sh_flags & SHF_ALLOC) != 0)
        {
            const char* elfAddr = elftmp->sectionData[i];

            ELF->sectionss[i].data = OSAL_Alloc(ELF->sectionss[i].trueDataSize);
            if(ELF->sectionss[i].data == NULL)
                goto oom;

            if(ELF->sectionss[i].meminfo->purpose == MEM_CODE)
            {
                MMDSP_copyCode(
                        (t_uint64*)ELF->sectionss[i].data,
                        elfAddr,
                        ELF->sectionss[i].trueDataSize);
            }
            else if(ELF->sectionss[i].meminfo->purpose == MEM_DATA &&
                    // Always 3 for data ELF->sectionss[i].meminfo->fileEntSize == 3 &&
                    ELF->sectionss[i].meminfo->memEntSize == 4)
            {
                MMDSP_copyData24(
                        (t_uint32*)ELF->sectionss[i].data,
                        elfAddr,
                        ELF->sectionss[i].trueDataSize);
            }
            else if(ELF->sectionss[i].meminfo->purpose == MEM_DATA &&
                    // Always 3 for data ELF->sectionss[i].meminfo->fileEntSize == 3 &&
                    ELF->sectionss[i].meminfo->memEntSize == 2)
            {
                MMDSP_copyData16(
                        (t_uint16*)ELF->sectionss[i].data,
                        elfAddr,
                        ELF->sectionss[i].trueDataSize);
            }
            else
                CM_ASSERT(0);
        }
    }

    // Copy relocation
    // Loop on all relocation section
    for(i=0; i < ELF->e_shnum; i++)
    {
        int sh_info;

        // Does this section is a relocation table (only RELA supported)
        if((ELF->sectionss[i].sh_type != SHT_RELA) ||
                ELF->sectionss[i].sh_size == 0) continue;

        // Copy only relocation for loaded section
        sh_info = ELF->sectionss[i].sh_info;
        if(ELF->sectionss[sh_info].meminfo != NULL)
        {
            const ElfXX_Sym* symtab;
            const char* strtab;
            ElfXX_Rela* rel_start;
            int n;

            ELF->sectionss[sh_info].relocationNumber = ELF->sectionss[i].sh_size / sizeof(ElfXX_Rela);
            ELF->sectionss[sh_info].relocations = (struct XXrelocation*)OSAL_Alloc_Zero(sizeof(struct XXrelocation) * ELF->sectionss[sh_info].relocationNumber);
            if(ELF->sectionss[sh_info].relocations == NULL)
                goto oom;

            symtab = (ElfXX_Sym *)elftmp->sectionData[ELF->sectionss[i].sh_link];
            strtab = elftmp->sectionData[ELF->sectionss[ELF->sectionss[i].sh_link].sh_link];
            rel_start = (ElfXX_Rela*)elftmp->sectionData[i];
            for(n = 0; n < ELF->sectionss[sh_info].relocationNumber; n++, rel_start++)
            {
                struct XXrelocation* relocation = &ELF->sectionss[sh_info].relocations[n];
                ElfXX_Xword r_info = swapXword(rel_start->r_info);
                int strtab_index = ELFXX_R_SYM(r_info);
                const char* symbol_name = &strtab[swapWord(symtab[strtab_index].st_name)];

                relocation->st_shndx = swapHalf(symtab[strtab_index].st_shndx);
                relocation->st_value = (t_uint32)swapXword(symtab[strtab_index].st_value);
                relocation->r_addend = swapXword(rel_start->r_addend);
                relocation->OffsetInElf = (t_uint32)swapXword(rel_start->r_offset) / ELF->sectionss[sh_info].meminfo->fileEntSize;
                relocation->type = ELFXX_R_TYPE(r_info);

                switch(relocation->st_shndx) {
                case SHN_UNDEF:
                    relocation->symbol_name = cm_StringDuplicate(symbol_name + 1); /* Remove '_' prefix */
                    if(relocation->symbol_name == NULL)
                        goto oom;
                    break;
                case SHN_COMMON:
                    ERROR("SHN_COMMON not handle for %s\n", symbol_name, 0, 0, 0, 0, 0);
                    goto invalid;
                }
            }
        }
    }

    *elfhandlePtr = elfhandle;
    return CM_OK;
invalid:
    ELF64_UnloadComponent(elfhandle);
    return CM_INVALID_ELF_FILE;
oom:
    ELF64_UnloadComponent(elfhandle);
    return CM_NO_MORE_MEMORY;
}

t_cm_error ELF64_ComputeSegment(
        t_elfdescription            *elfhandle,
        t_tmp_elfdescription        *elftmp)
{
    struct XXElf* ELF = elfhandle->ELF;
    int i;

    for(i = 0; i < ELF->e_shnum; i++)
    {
        ELF->sectionss[i].offsetInSegment =  0xFFFFFFFF;

        if(ELF->sectionss[i].sh_type == SHT_PROGBITS || ELF->sectionss[i].sh_type == SHT_NOBITS) {
            // This is a loadable memory (memory size could be zero since we can have symbol on it)...
            const t_elfmemory* meminfo = ELF->sectionss[i].meminfo;

            if(meminfo != NULL) {
                // Which correspond to MPC memory

                if(elftmp->isExecutable)
                {
                    if(! elfhandle->segments[meminfo->id].sumSizeSetted)
                    {
                        CM_ASSERT(ELF->sectionss[i].sh_addr >= meminfo->startAddr * meminfo->fileEntSize);

                        elfhandle->segments[meminfo->id].sumSizeSetted = TRUE;
                        elfhandle->segments[meminfo->id].sumSize = ELF->sectionss[i].sh_addr - meminfo->startAddr * meminfo->fileEntSize;
                    }
                    else
                        CM_ASSERT(elfhandle->segments[meminfo->id].sumSize == ELF->sectionss[i].sh_addr - meminfo->startAddr * meminfo->fileEntSize);
                }
                else
                {
                    while(elfhandle->segments[meminfo->id].sumSize % ELF->sectionss[i].sh_addralign != 0)
                        elfhandle->segments[meminfo->id].sumSize++;
                }

                elfhandle->segments[meminfo->id].maxAlign = max(elfhandle->segments[meminfo->id].maxAlign, ELF->sectionss[i].sh_addralign);
                ELF->sectionss[i].offsetInSegment = elfhandle->segments[meminfo->id].sumSize / meminfo->fileEntSize;
                elfhandle->segments[meminfo->id].sumSize += ELF->sectionss[i].sh_size;
            }
         } else if(ELF->sectionss[i].sh_type == SHT_RELA && ELF->sectionss[i].sh_info == elftmp->nmfSectionIndex) {
             int secsym = ELF->sectionss[i].sh_link;
             elftmp->relaNmfSegment = (ElfXX_Rela*)elftmp->sectionData[i];
             elftmp->relaNmfSegmentEnd = (ElfXX_Rela*)((t_uint32)elftmp->relaNmfSegment + ELF->sectionss[i].sh_size);
             elftmp->relaNmfSegmentSymbols = (ElfXX_Sym*)elftmp->sectionData[secsym];
             elftmp->relaNmfSegmentStrings = elftmp->sectionData[ELF->sectionss[secsym].sh_link];
         }
    }

    return CM_OK;
}

void ELF64_UnloadComponent(
        t_elfdescription            *elfhandle)
{
    struct XXElf* ELF = elfhandle->ELF;
    int i, n;

    for(i = 0; i < ELF->e_shnum; i++)
    {
        if(ELF->sectionss[i].relocations != NULL)
        {
            for(n = 0; n < ELF->sectionss[i].relocationNumber; n++)
                cm_StringRelease(ELF->sectionss[i].relocations[n].symbol_name);
            OSAL_Free(ELF->sectionss[i].relocations);
        }

        OSAL_Free((void*)ELF->sectionss[i].data);
    }
    OSAL_Free(elfhandle);
}

t_cm_error ELF64_loadSegment(
        t_elfdescription            *elfhandle,
        t_memory_handle             *memory,
        t_memory_property           property)
{
    struct XXElf* ELF = elfhandle->ELF;
    int i;

    /*
     * Copy ELF data in this segment
     */
    for(i = 0; i < ELF->e_shnum; i++)
    {
        const t_elfmemory* mapping = ELF->sectionss[i].meminfo;

        if(mapping == NULL)
            continue;
        if((! (ELF->sectionss[i].sh_flags & SHF_ALLOC)) || (ELF->sectionss[i].sh_size == 0))
            continue;

        // This is a loadable memory ...
        if(
                (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) ||
                (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) )
        {
            // Where memory exist and waited share/private correspond
            t_uint32 remoteData = elfhandle->segments[mapping->id].hostAddr +
                    ELF->sectionss[i].offsetInSegment * mapping->memEntSize;

            if(ELF->sectionss[i].sh_type != SHT_NOBITS)
            {
                LOG_INTERNAL(2, "loadSection(%s, 0x%x, 0x%x, 0x%08x)\n",
                        ELF->sectionss[i].sectionName, remoteData, ELF->sectionss[i].trueDataSize,
                        (t_uint32)ELF->sectionss[i].data, 0, 0);

                MMDSP_copySection((t_uint32)ELF->sectionss[i].data, remoteData, ELF->sectionss[i].trueDataSize);
            }
            else
            {
                LOG_INTERNAL(2, "bzeroSection(%s, 0x%x, 0x%x)\n",
                        ELF->sectionss[i].sectionName, remoteData, ELF->sectionss[i].trueDataSize, 0, 0, 0);

                MMDSP_bzeroSection(remoteData, ELF->sectionss[i].trueDataSize);
            }
        }
    }

    return CM_OK;
}



static const t_elfmemory* getSectionAddress(
        t_memory_handle *memories,
        t_elfdescription *elfhandle,
        t_uint32 sectionIdx,
        t_uint32 *sectionOffset,
        t_cm_logical_address *sectionAddr) {
    struct XXElf* ELF = elfhandle->ELF;
    const t_elfmemory* mapping = ELF->sectionss[sectionIdx].meminfo;

    if(mapping != NULL) {
        *sectionOffset = (elfhandle->segments[mapping->id].mpcAddr +
                ELF->sectionss[sectionIdx].offsetInSegment);

        *sectionAddr = (t_cm_logical_address)(elfhandle->segments[mapping->id].hostAddr +
                ELF->sectionss[sectionIdx].offsetInSegment * mapping->memEntSize);
    }

    return mapping;
}

static t_uint32 getSymbolAddress(
        t_memory_handle             *memories,
        t_elfdescription            *elfhandle,
        t_uint32                    symbolSectionIdx,
        t_uint32                    symbolOffet) {
    struct XXElf* ELF = elfhandle->ELF;
    const t_elfmemory* mapping = ELF->sectionss[symbolSectionIdx].meminfo;

    if(mapping == NULL)
        return 0xFFFFFFFF;
    // CM_ASSERT(elfhandle->segments[mapping->id].sumSize != 0);
    // CM_ASSERT(elfhandle->sections[symbolSectionIdx].offsetInSegment != 0xFFFFFFFF);

    return elfhandle->segments[mapping->id].mpcAddr +
        ELF->sectionss[symbolSectionIdx].offsetInSegment +
        symbolOffet;
}

#if 0
t_bool ELFXX_getSymbolLocation(
        const t_mpcal_memory    *mpcalmemory,
        t_elfdescription        *elf,
        char                    *symbolName,
        const t_elfmemory       **memory,
        t_uint32                *offset) {
    const ElfXX_Ehdr *header = (ElfXX_Ehdr*)elf->elfdata;
    const ElfXX_Shdr *sections = (ElfXX_Shdr*)&elf->elfdata[swapXword(header->e_shoff)];
    const char *strings = &elf->elfdata[swapXword(sections[swapHalf(header->e_shstrndx)].sh_offset)];
    int len = cm_StringLength(symbolName, 256); // TO BE FIXED
    int i;

    for(i = 0; i < ELF->e_shnum; i++)
    {
        ElfXX_Sym* symtab;
        const char* strtab;
        unsigned int size, j;

        if(ELF->sectionss[i].sh_type != SHT_SYMTAB && ELF->sectionss[i].sh_type != SHT_DYNSYM) continue;

        // Section is a symbol table
        symtab = (ElfXX_Sym*)&elf->elfdata[swapXword(sections[i].sh_offset)];
        strtab = &elf->elfdata[swapXword(sections[swapWord(sections[i].sh_link)].sh_offset)];
        size = ELF->sectionss[i].sh_size / (unsigned int)swapXword(sections[i].sh_entsize);

        for(j = 0; j < size; j++) {
            const char* foundName = &strtab[swapWord(symtab[j].st_name)];

            if(cm_StringCompare(symbolName, foundName, len) == 0) {
                if(swapHalf(symtab[j].st_shndx) != SHN_UNDEF) {
                    int sectionIdx = (int)swapHalf(symtab[j].st_shndx);
                    ElfXX_Xword sh_flags = swapXword(sections[sectionIdx].sh_flags);

                    *memory = mpcalmemory->getMappingByName(&strings[swapWord(sections[sectionIdx].sh_name)],
                            sh_flags & SHF_WRITE ? MEM_RW : (sh_flags & SHF_EXECINSTR ? MEM_X : MEM_RO));
                    *offset = (t_uint32)swapXword(symtab[j].st_value);

                    return 1;
                }
            }
        }
    }
    return 0;
}
#endif

t_cm_error ELF64_relocateSegments(
        t_memory_handle             *memories,
        t_elfdescription            *elfhandle,
        t_memory_property           property,
        void                        *cbContext) {
    struct XXElf* ELF = elfhandle->ELF;
    int sec, n;

    // Loop on all relocation section
    for(sec=0; sec < ELF->e_shnum; sec++)
    {
        t_cm_logical_address sectionAddr = 0;
        t_uint32 sectionOffset = 0;
        const t_elfmemory* mapping;

        if(ELF->sectionss[sec].relocations == NULL)
            continue;

        // Relocate only section in memory
        mapping = getSectionAddress(memories,
                elfhandle,
                sec,
                &sectionOffset,
                &sectionAddr);
        if(mapping == NULL)
            continue;

        if(
                (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) ||
                (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) )
        {
            LOG_INTERNAL(2, "relocSection(%s)\n", ELF->sectionss[sec].sectionName, 0, 0, 0, 0, 0);

            for(n = 0; n < ELF->sectionss[sec].relocationNumber; n++)
            {
                struct XXrelocation* relocation = &ELF->sectionss[sec].relocations[n];
                t_uint32 symbol_addr;
                char* relocAddr = (char*)(sectionAddr + relocation->OffsetInElf * mapping->memEntSize);

                switch(relocation->st_shndx) {
                case SHN_ABS:              // Absolute external reference
                    symbol_addr = relocation->st_value;
                    break;
                case SHN_UNDEF:            // External reference
                     // LOG_INTERNAL(0, "cm_resolvSymbol(%d, %s)\n", relocation->type, relocation->symbol_name, 0,0, 0, 0);
                    symbol_addr = cm_resolvSymbol(cbContext,
                            relocation->type,
                            relocation->symbol_name,
                            relocAddr);
                    if(symbol_addr == 0x0) { // Not defined symbol
                        ERROR("Symbol %s not found\n", relocation->symbol_name, 0, 0, 0, 0, 0);
                        return CM_INVALID_ELF_FILE;
                    } else if(symbol_addr == 0xFFFFFFFE) { // OOM
                        return CM_NO_MORE_MEMORY;
                    } else if(symbol_addr == 0xFFFFFFFF) { // Defined inside static binding
                        continue;
                    }
                    break;
                default:                   // Internal reference in loaded section
                    symbol_addr = getSymbolAddress(
                            memories,
                            elfhandle,
                            (t_uint32)relocation->st_shndx,
                            relocation->st_value);
                    if(symbol_addr == 0xFFFFFFFF) {
                        ERROR("Symbol in section %s+%d not loaded\n",
                                ELF->sectionss[relocation->st_shndx].sectionName,
                                relocation->st_value, 0, 0, 0, 0);
                        return CM_INVALID_ELF_FILE;
                    }
                    break;
                }

                symbol_addr += relocation->r_addend;

                MMDSP_performRelocation(
                        relocation->type,
                        relocation->symbol_name,
                        symbol_addr,
                        relocAddr,
                        ELF->sectionss[sec].data + relocation->OffsetInElf * mapping->memEntSize,
                        sectionOffset + relocation->OffsetInElf);
            }
        }
    }

    return CM_OK;
}

t_cm_error ELF64_getRelocationMemory(
        t_elfdescription            *elfhandle,
        t_tmp_elfdescription        *elftmp,
        t_uint32                    offsetInNmf,
        t_memory_reference          *memory) {
    struct XXElf* ELF = elfhandle->ELF;
    const ElfXX_Rela* rel_start;
    const ElfXX_Sym* relaNmfSegmentSymbols = (ElfXX_Sym*)elftmp->relaNmfSegmentSymbols;

    for(rel_start = (ElfXX_Rela*)elftmp->relaNmfSegment; rel_start < (ElfXX_Rela*)elftmp->relaNmfSegmentEnd; rel_start++)
    {
        if((t_uint32)swapXword(rel_start->r_offset) == offsetInNmf)
        {
            int strtab_index = ELFXX_R_SYM(swapXword(rel_start->r_info));
            int sectionIdx = (int)swapHalf(relaNmfSegmentSymbols[strtab_index].st_shndx);

            memory->memory = ELF->sectionss[sectionIdx].meminfo;

            if(memory->memory != NULL) {
                memory->offset = (
                        ELF->sectionss[sectionIdx].offsetInSegment +                           // Offset in Segment
                        (t_uint32)swapXword(relaNmfSegmentSymbols[strtab_index].st_value) +    // Offset in Elf Section
                        (t_uint32)swapXword(rel_start->r_addend));                                  // Addend

                return CM_OK;
            } else {
                const char* symbol_name = &elftmp->relaNmfSegmentStrings[swapWord(relaNmfSegmentSymbols[strtab_index].st_name)];
                ERROR("Symbol %s not found\n", symbol_name, 0, 0, 0, 0, 0);
                return CM_INVALID_ELF_FILE;
            }
        }
    }

    ERROR("Unknown relocation error\n", 0, 0, 0, 0, 0, 0);
    return CM_INVALID_ELF_FILE;
}