1/*
2 * Copyright (c) 1999-2004 University of New South Wales
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <strops.h>
8#include <binaries/elf/elf.h>
9
10int
11elf32_checkFile(struct Elf32_Header *file)
12{
13    if (file->e_ident[EI_MAG0] != ELFMAG0
14            || file->e_ident[EI_MAG1] != ELFMAG1
15            || file->e_ident[EI_MAG2] != ELFMAG2
16            || file->e_ident[EI_MAG3] != ELFMAG3) {
17        return -1;    /* not an elf file */
18    }
19    if (file->e_ident[EI_CLASS] != ELFCLASS32) {
20        return -2;    /* not 32-bit file */
21    }
22    return 0;		/* elf file looks OK */
23}
24
25/*
26 * Returns the number of program segments in this elf file.
27 */
28unsigned
29elf32_getNumSections(struct Elf32_Header *elfFile)
30{
31    return elfFile->e_shnum;
32}
33
34char *
35elf32_getStringTable(struct Elf32_Header *elfFile)
36{
37    struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
38    return (char *)elfFile + sections[elfFile->e_shstrndx].sh_offset;
39}
40
41/* Returns a pointer to the program segment table, which is an array of
42 * ELF32_Phdr_t structs.  The size of the array can be found by calling
43 * getNumProgramSegments. */
44struct Elf32_Phdr *
45elf32_getProgramSegmentTable(struct Elf32_Header *elfFile) {
46    struct Elf32_Header *fileHdr = elfFile;
47    return (struct Elf32_Phdr *) (fileHdr->e_phoff + (long) elfFile);
48}
49
50/* Returns the number of program segments in this elf file. */
51uint16_t
52elf32_getNumProgramHeaders(struct Elf32_Header *elfFile)
53{
54    struct Elf32_Header *fileHdr = elfFile;
55    return fileHdr->e_phnum;
56}
57
58char *
59elf32_getSectionName(struct Elf32_Header *elfFile, int i)
60{
61    struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
62    char *str_table = elf32_getSegmentStringTable(elfFile);
63    if (str_table == NULL) {
64        return "<corrupted>";
65    } else {
66        return str_table + sections[i].sh_name;
67    }
68}
69
70uint32_t
71elf32_getSectionSize(struct Elf32_Header *elfFile, int i)
72{
73    struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
74    return sections[i].sh_size;
75}
76
77uint32_t
78elf32_getSectionAddr(struct Elf32_Header *elfFile, int i)
79{
80    struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
81    return sections[i].sh_addr;
82}
83
84void *
85elf32_getSection(struct Elf32_Header *elfFile, int i)
86{
87    struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
88    return (char *)elfFile + sections[i].sh_offset;
89}
90
91void *
92elf32_getSectionNamed(struct Elf32_Header *elfFile, char *str)
93{
94    int numSections = elf32_getNumSections(elfFile);
95    int i;
96    for (i = 0; i < numSections; i++) {
97        if (strcmp(str, elf32_getSectionName(elfFile, i)) == 0) {
98            return elf32_getSection(elfFile, i);
99        }
100    }
101    return NULL;
102}
103
104char *
105elf32_getSegmentStringTable(struct Elf32_Header *elfFile)
106{
107    struct Elf32_Header *fileHdr = (struct Elf32_Header *) elfFile;
108    if (fileHdr->e_shstrndx == 0) {
109        return NULL;
110    } else {
111        return elf32_getStringTable(elfFile);
112    }
113}
114
115#ifdef ELF_DEBUG
116void
117elf32_printStringTable(struct Elf32_Header *elfFile)
118{
119    int counter;
120    struct Elf32_Shdr *sections = elf32_getSectionTable(elfFile);
121    char * stringTable;
122
123    if (!sections) {
124        printf("No sections.\n");
125        return;
126    }
127
128    stringTable = ((void *)elfFile) + sections[elfFile->e_shstrndx].sh_offset;
129
130    printf("File is %p; sections is %p; string table is %p\n", elfFile, sections, stringTable);
131
132    for (counter = 0; counter < sections[elfFile->e_shstrndx].sh_size; counter++) {
133        printf("%02x %c ", stringTable[counter],
134               stringTable[counter] >= 0x20 ? stringTable[counter] : '.');
135    }
136}
137#endif
138
139int
140elf32_getSegmentType (struct Elf32_Header *elfFile, int segment)
141{
142    return elf32_getProgramSegmentTable(elfFile)[segment].p_type;
143}
144
145void
146elf32_getSegmentInfo(struct Elf32_Header *elfFile, int segment, uint64_t *p_vaddr, uint64_t *p_addr, uint64_t *p_filesz, uint64_t *p_offset, uint64_t *p_memsz)
147{
148    struct Elf32_Phdr *segments;
149
150    segments = elf32_getProgramSegmentTable(elfFile);
151    *p_addr = segments[segment].p_paddr;
152    *p_vaddr = segments[segment].p_vaddr;
153    *p_filesz = segments[segment].p_filesz;
154    *p_offset = segments[segment].p_offset;
155    *p_memsz = segments[segment].p_memsz;
156}
157
158uint32_t
159elf32_getEntryPoint (struct Elf32_Header *elfFile)
160{
161    return elfFile->e_entry;
162}
163