slavio_serial fixes (Blue Swirl)
[qemu] / hw / elf_ops.h
1 #ifdef BSWAP_NEEDED
2 static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
3 {
4     bswap16s(&ehdr->e_type);                    /* Object file type */
5     bswap16s(&ehdr->e_machine);         /* Architecture */
6     bswap32s(&ehdr->e_version);         /* Object file version */
7     bswapSZs(&ehdr->e_entry);           /* Entry point virtual address */
8     bswapSZs(&ehdr->e_phoff);           /* Program header table file offset */
9     bswapSZs(&ehdr->e_shoff);           /* Section header table file offset */
10     bswap32s(&ehdr->e_flags);           /* Processor-specific flags */
11     bswap16s(&ehdr->e_ehsize);          /* ELF header size in bytes */
12     bswap16s(&ehdr->e_phentsize);               /* Program header table entry size */
13     bswap16s(&ehdr->e_phnum);           /* Program header table entry count */
14     bswap16s(&ehdr->e_shentsize);               /* Section header table entry size */
15     bswap16s(&ehdr->e_shnum);           /* Section header table entry count */
16     bswap16s(&ehdr->e_shstrndx);                /* Section header string table index */
17 }
18
19 static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
20 {
21     bswap32s(&phdr->p_type);                    /* Segment type */
22     bswapSZs(&phdr->p_offset);          /* Segment file offset */
23     bswapSZs(&phdr->p_vaddr);           /* Segment virtual address */
24     bswapSZs(&phdr->p_paddr);           /* Segment physical address */
25     bswapSZs(&phdr->p_filesz);          /* Segment size in file */
26     bswapSZs(&phdr->p_memsz);           /* Segment size in memory */
27     bswap32s(&phdr->p_flags);           /* Segment flags */
28     bswapSZs(&phdr->p_align);           /* Segment alignment */
29 }
30
31 static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
32 {
33     bswap32s(&shdr->sh_name);
34     bswap32s(&shdr->sh_type);
35     bswapSZs(&shdr->sh_flags);
36     bswapSZs(&shdr->sh_addr);
37     bswapSZs(&shdr->sh_offset);
38     bswapSZs(&shdr->sh_size);
39     bswap32s(&shdr->sh_link);
40     bswap32s(&shdr->sh_info);
41     bswapSZs(&shdr->sh_addralign);
42     bswapSZs(&shdr->sh_entsize);
43 }
44
45 static void glue(bswap_sym, SZ)(struct elf_sym *sym)
46 {
47     bswap32s(&sym->st_name);
48     bswapSZs(&sym->st_value);
49     bswapSZs(&sym->st_size);
50     bswap16s(&sym->st_shndx);
51 }
52 #endif
53
54 static int glue(find_phdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, elf_word type)
55 {
56     int i, retval;
57
58     retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
59     if (retval < 0)
60         return -1;
61
62     for (i = 0; i < ehdr->e_phnum; i++) {
63         retval = read(fd, phdr, sizeof(*phdr));
64         if (retval < 0)
65             return -1;
66         glue(bswap_phdr, SZ)(phdr);
67         if (phdr->p_type == type)
68             return 0;
69     }
70     return -1;
71 }
72
73 static void * glue(find_shdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
74 {
75     int i, retval;
76
77     retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
78     if (retval < 0)
79         return NULL;
80
81     for (i = 0; i < ehdr->e_shnum; i++) {
82         retval = read(fd, shdr, sizeof(*shdr));
83         if (retval < 0)
84             return NULL;
85         glue(bswap_shdr, SZ)(shdr);
86         if (shdr->sh_type == type)
87             return qemu_malloc(shdr->sh_size);
88     }
89     return NULL;
90 }
91
92 static void * glue(find_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
93 {
94     int retval;
95
96     retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
97     if (retval < 0)
98         return NULL;
99
100     retval = read(fd, shdr, sizeof(*shdr));
101     if (retval < 0)
102         return NULL;
103     glue(bswap_shdr, SZ)(shdr);
104     if (shdr->sh_type == SHT_STRTAB)
105         return qemu_malloc(shdr->sh_size);;
106     return NULL;
107 }
108
109 static int glue(read_program, SZ)(int fd, struct elf_phdr *phdr, void *dst, elf_word entry)
110 {
111     int retval;
112     retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
113     if (retval < 0)
114         return -1;
115     return read(fd, dst, phdr->p_filesz);
116 }
117
118 static int glue(read_section, SZ)(int fd, struct elf_shdr *s, void *dst)
119 {
120     int retval;
121
122     retval = lseek(fd, s->sh_offset, SEEK_SET);
123     if (retval < 0)
124         return -1;
125     retval = read(fd, dst, s->sh_size);
126     if (retval < 0)
127         return -1;
128     return 0;
129 }
130
131 static void * glue(process_section, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
132 {
133     void *dst;
134
135     dst = glue(find_shdr, SZ)(ehdr, fd, shdr, type);
136     if (!dst)
137         goto error;
138
139     if (glue(read_section, SZ)(fd, shdr, dst))
140         goto error;
141     return dst;
142  error:
143     qemu_free(dst);
144     return NULL;
145 }
146
147 static void * glue(process_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
148 {
149     void *dst;
150
151     dst = glue(find_strtab, SZ)(ehdr, fd, shdr, symtab);
152     if (!dst)
153         goto error;
154
155     if (glue(read_section, SZ)(fd, shdr, dst))
156         goto error;
157     return dst;
158  error:
159     qemu_free(dst);
160     return NULL;
161 }
162
163 static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd)
164 {
165     struct elf_shdr symtab, strtab;
166     struct elf_sym *syms;
167 #if (SZ == 64)
168     struct elf32_sym *syms32;
169 #endif
170     struct syminfo *s;
171     int nsyms, i;
172     char *str;
173
174     /* Symbol table */
175     syms = glue(process_section, SZ)(ehdr, fd, &symtab, SHT_SYMTAB);
176     if (!syms)
177         return;
178
179     nsyms = symtab.sh_size / sizeof(struct elf_sym);
180 #if (SZ == 64)
181     syms32 = qemu_mallocz(nsyms * sizeof(struct elf32_sym));
182 #endif
183     for (i = 0; i < nsyms; i++) {
184         glue(bswap_sym, SZ)(&syms[i]);
185 #if (SZ == 64)
186         syms32[i].st_name = syms[i].st_name;
187         syms32[i].st_info = syms[i].st_info;
188         syms32[i].st_other = syms[i].st_other;
189         syms32[i].st_shndx = syms[i].st_shndx;
190         syms32[i].st_value = syms[i].st_value & 0xffffffff;
191         syms32[i].st_size = syms[i].st_size & 0xffffffff;
192 #endif
193     }
194     /* String table */
195     str = glue(process_strtab, SZ)(ehdr, fd, &strtab, &symtab);
196     if (!str)
197         goto error_freesyms;
198
199     /* Commit */
200     s = qemu_mallocz(sizeof(*s));
201 #if (SZ == 64)
202     s->disas_symtab = syms32;
203     qemu_free(syms);
204 #else
205     s->disas_symtab = syms;
206 #endif
207     s->disas_num_syms = nsyms;
208     s->disas_strtab = str;
209     s->next = syminfos;
210     syminfos = s;
211     return;
212  error_freesyms:
213 #if (SZ == 64)
214     qemu_free(syms32);
215 #endif
216     qemu_free(syms);
217     return;
218 }