root / hw / magic-load.c @ bc2c3909
History | View | Annotate | Download (4.5 kB)
1 | 420557e8 | bellard | #include "vl.h" |
---|---|---|---|
2 | 420557e8 | bellard | #include "disas.h" |
3 | e80cfcfc | bellard | #include "exec-all.h" |
4 | e80cfcfc | bellard | |
5 | e80cfcfc | bellard | struct exec
|
6 | e80cfcfc | bellard | { |
7 | e80cfcfc | bellard | uint32_t a_info; /* Use macros N_MAGIC, etc for access */
|
8 | e80cfcfc | bellard | uint32_t a_text; /* length of text, in bytes */
|
9 | e80cfcfc | bellard | uint32_t a_data; /* length of data, in bytes */
|
10 | e80cfcfc | bellard | uint32_t a_bss; /* length of uninitialized data area, in bytes */
|
11 | e80cfcfc | bellard | uint32_t a_syms; /* length of symbol table data in file, in bytes */
|
12 | e80cfcfc | bellard | uint32_t a_entry; /* start address */
|
13 | e80cfcfc | bellard | uint32_t a_trsize; /* length of relocation info for text, in bytes */
|
14 | e80cfcfc | bellard | uint32_t a_drsize; /* length of relocation info for data, in bytes */
|
15 | e80cfcfc | bellard | }; |
16 | e80cfcfc | bellard | |
17 | e80cfcfc | bellard | #ifdef BSWAP_NEEDED
|
18 | e80cfcfc | bellard | static void bswap_ahdr(struct exec *e) |
19 | e80cfcfc | bellard | { |
20 | e80cfcfc | bellard | bswap32s(&e->a_info); |
21 | e80cfcfc | bellard | bswap32s(&e->a_text); |
22 | e80cfcfc | bellard | bswap32s(&e->a_data); |
23 | e80cfcfc | bellard | bswap32s(&e->a_bss); |
24 | e80cfcfc | bellard | bswap32s(&e->a_syms); |
25 | e80cfcfc | bellard | bswap32s(&e->a_entry); |
26 | e80cfcfc | bellard | bswap32s(&e->a_trsize); |
27 | e80cfcfc | bellard | bswap32s(&e->a_drsize); |
28 | e80cfcfc | bellard | } |
29 | e80cfcfc | bellard | #else
|
30 | e80cfcfc | bellard | #define bswap_ahdr(x) do { } while (0) |
31 | e80cfcfc | bellard | #endif
|
32 | e80cfcfc | bellard | |
33 | e80cfcfc | bellard | #define N_MAGIC(exec) ((exec).a_info & 0xffff) |
34 | e80cfcfc | bellard | #define OMAGIC 0407 |
35 | e80cfcfc | bellard | #define NMAGIC 0410 |
36 | e80cfcfc | bellard | #define ZMAGIC 0413 |
37 | e80cfcfc | bellard | #define QMAGIC 0314 |
38 | e80cfcfc | bellard | #define _N_HDROFF(x) (1024 - sizeof (struct exec)) |
39 | e80cfcfc | bellard | #define N_TXTOFF(x) \
|
40 | e80cfcfc | bellard | (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \ |
41 | e80cfcfc | bellard | (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec))) |
42 | e80cfcfc | bellard | #define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0) |
43 | e80cfcfc | bellard | #define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
|
44 | e80cfcfc | bellard | #define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1)) |
45 | e80cfcfc | bellard | |
46 | e80cfcfc | bellard | #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
|
47 | e80cfcfc | bellard | |
48 | e80cfcfc | bellard | #define N_DATADDR(x) \
|
49 | e80cfcfc | bellard | (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \ |
50 | e80cfcfc | bellard | : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) |
51 | e80cfcfc | bellard | |
52 | 420557e8 | bellard | |
53 | 420557e8 | bellard | #define ELF_CLASS ELFCLASS32
|
54 | 420557e8 | bellard | #define ELF_DATA ELFDATA2MSB
|
55 | 420557e8 | bellard | #define ELF_ARCH EM_SPARC
|
56 | 420557e8 | bellard | |
57 | 420557e8 | bellard | #include "elf.h" |
58 | 420557e8 | bellard | |
59 | 3475187d | bellard | #ifndef BSWAP_NEEDED
|
60 | 3475187d | bellard | #define bswap_ehdr32(e) do { } while (0) |
61 | 3475187d | bellard | #define bswap_phdr32(e) do { } while (0) |
62 | 3475187d | bellard | #define bswap_shdr32(e) do { } while (0) |
63 | 3475187d | bellard | #define bswap_sym32(e) do { } while (0) |
64 | 3475187d | bellard | #ifdef TARGET_SPARC64
|
65 | 3475187d | bellard | #define bswap_ehdr64(e) do { } while (0) |
66 | 3475187d | bellard | #define bswap_phdr64(e) do { } while (0) |
67 | 3475187d | bellard | #define bswap_shdr64(e) do { } while (0) |
68 | 3475187d | bellard | #define bswap_sym64(e) do { } while (0) |
69 | 3475187d | bellard | #endif
|
70 | 420557e8 | bellard | #endif
|
71 | 420557e8 | bellard | |
72 | 3475187d | bellard | #define SZ 32 |
73 | 3475187d | bellard | #define elf_word uint32_t
|
74 | 3475187d | bellard | #define bswapSZs bswap32s
|
75 | 3475187d | bellard | #include "elf_ops.h" |
76 | 3475187d | bellard | |
77 | 3475187d | bellard | #ifdef TARGET_SPARC64
|
78 | 3475187d | bellard | #undef elfhdr
|
79 | 3475187d | bellard | #undef elf_phdr
|
80 | 3475187d | bellard | #undef elf_shdr
|
81 | 3475187d | bellard | #undef elf_sym
|
82 | 3475187d | bellard | #undef elf_note
|
83 | 3475187d | bellard | #undef elf_word
|
84 | 3475187d | bellard | #undef bswapSZs
|
85 | 3475187d | bellard | #undef SZ
|
86 | 3475187d | bellard | #define elfhdr elf64_hdr
|
87 | 3475187d | bellard | #define elf_phdr elf64_phdr
|
88 | 3475187d | bellard | #define elf_note elf64_note
|
89 | 3475187d | bellard | #define elf_shdr elf64_shdr
|
90 | 3475187d | bellard | #define elf_sym elf64_sym
|
91 | 3475187d | bellard | #define elf_word uint64_t
|
92 | 3475187d | bellard | #define bswapSZs bswap64s
|
93 | 3475187d | bellard | #define SZ 64 |
94 | 3475187d | bellard | #include "elf_ops.h" |
95 | 3475187d | bellard | #endif
|
96 | 420557e8 | bellard | |
97 | e80cfcfc | bellard | int load_elf(const char *filename, uint8_t *addr) |
98 | 8d5f07fa | bellard | { |
99 | 3475187d | bellard | struct elf32_hdr ehdr;
|
100 | 8d5f07fa | bellard | int retval, fd;
|
101 | 3475187d | bellard | Elf32_Half machine; |
102 | 420557e8 | bellard | |
103 | 8d5f07fa | bellard | fd = open(filename, O_RDONLY | O_BINARY); |
104 | 8d5f07fa | bellard | if (fd < 0) |
105 | 8d5f07fa | bellard | goto error;
|
106 | 420557e8 | bellard | |
107 | 8d5f07fa | bellard | retval = read(fd, &ehdr, sizeof(ehdr));
|
108 | 8d5f07fa | bellard | if (retval < 0) |
109 | 8d5f07fa | bellard | goto error;
|
110 | 420557e8 | bellard | |
111 | 8d5f07fa | bellard | if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E' |
112 | 3475187d | bellard | || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F') |
113 | 8d5f07fa | bellard | goto error;
|
114 | 3475187d | bellard | machine = tswap16(ehdr.e_machine); |
115 | 3475187d | bellard | if (machine == EM_SPARC || machine == EM_SPARC32PLUS) {
|
116 | 3475187d | bellard | struct elf32_phdr phdr;
|
117 | 420557e8 | bellard | |
118 | 3475187d | bellard | bswap_ehdr32(&ehdr); |
119 | 420557e8 | bellard | |
120 | 3475187d | bellard | if (find_phdr32(&ehdr, fd, &phdr, PT_LOAD))
|
121 | 3475187d | bellard | goto error;
|
122 | 3475187d | bellard | retval = read_program32(fd, &phdr, addr, ehdr.e_entry); |
123 | 3475187d | bellard | if (retval < 0) |
124 | 3475187d | bellard | goto error;
|
125 | 3475187d | bellard | load_symbols32(&ehdr, fd); |
126 | 3475187d | bellard | } |
127 | 3475187d | bellard | #ifdef TARGET_SPARC64
|
128 | 3475187d | bellard | else if (machine == EM_SPARCV9) { |
129 | 3475187d | bellard | struct elf64_hdr ehdr64;
|
130 | 3475187d | bellard | struct elf64_phdr phdr;
|
131 | 3475187d | bellard | |
132 | 3475187d | bellard | lseek(fd, 0, SEEK_SET);
|
133 | 3475187d | bellard | |
134 | 3475187d | bellard | retval = read(fd, &ehdr64, sizeof(ehdr64));
|
135 | 3475187d | bellard | if (retval < 0) |
136 | 3475187d | bellard | goto error;
|
137 | 3475187d | bellard | |
138 | 3475187d | bellard | bswap_ehdr64(&ehdr64); |
139 | 3475187d | bellard | |
140 | 3475187d | bellard | if (find_phdr64(&ehdr64, fd, &phdr, PT_LOAD))
|
141 | 3475187d | bellard | goto error;
|
142 | 3475187d | bellard | retval = read_program64(fd, &phdr, addr, ehdr64.e_entry); |
143 | 3475187d | bellard | if (retval < 0) |
144 | 3475187d | bellard | goto error;
|
145 | 3475187d | bellard | load_symbols64(&ehdr64, fd); |
146 | 3475187d | bellard | } |
147 | 3475187d | bellard | #endif
|
148 | 420557e8 | bellard | |
149 | 8d5f07fa | bellard | close(fd); |
150 | 8d5f07fa | bellard | return retval;
|
151 | 8d5f07fa | bellard | error:
|
152 | 8d5f07fa | bellard | close(fd); |
153 | 8d5f07fa | bellard | return -1; |
154 | 420557e8 | bellard | } |
155 | 420557e8 | bellard | |
156 | e80cfcfc | bellard | int load_aout(const char *filename, uint8_t *addr) |
157 | 420557e8 | bellard | { |
158 | e80cfcfc | bellard | int fd, size, ret;
|
159 | e80cfcfc | bellard | struct exec e;
|
160 | e80cfcfc | bellard | uint32_t magic; |
161 | 420557e8 | bellard | |
162 | 420557e8 | bellard | fd = open(filename, O_RDONLY | O_BINARY); |
163 | 420557e8 | bellard | if (fd < 0) |
164 | 420557e8 | bellard | return -1; |
165 | e80cfcfc | bellard | |
166 | e80cfcfc | bellard | size = read(fd, &e, sizeof(e));
|
167 | 420557e8 | bellard | if (size < 0) |
168 | 420557e8 | bellard | goto fail;
|
169 | e80cfcfc | bellard | |
170 | e80cfcfc | bellard | bswap_ahdr(&e); |
171 | e80cfcfc | bellard | |
172 | e80cfcfc | bellard | magic = N_MAGIC(e); |
173 | e80cfcfc | bellard | switch (magic) {
|
174 | e80cfcfc | bellard | case ZMAGIC:
|
175 | e80cfcfc | bellard | case QMAGIC:
|
176 | e80cfcfc | bellard | case OMAGIC:
|
177 | e80cfcfc | bellard | lseek(fd, N_TXTOFF(e), SEEK_SET); |
178 | e80cfcfc | bellard | size = read(fd, addr, e.a_text + e.a_data); |
179 | e80cfcfc | bellard | if (size < 0) |
180 | e80cfcfc | bellard | goto fail;
|
181 | e80cfcfc | bellard | break;
|
182 | e80cfcfc | bellard | case NMAGIC:
|
183 | e80cfcfc | bellard | lseek(fd, N_TXTOFF(e), SEEK_SET); |
184 | e80cfcfc | bellard | size = read(fd, addr, e.a_text); |
185 | e80cfcfc | bellard | if (size < 0) |
186 | e80cfcfc | bellard | goto fail;
|
187 | e80cfcfc | bellard | ret = read(fd, addr + N_DATADDR(e), e.a_data); |
188 | e80cfcfc | bellard | if (ret < 0) |
189 | e80cfcfc | bellard | goto fail;
|
190 | e80cfcfc | bellard | size += ret; |
191 | e80cfcfc | bellard | break;
|
192 | e80cfcfc | bellard | default:
|
193 | e80cfcfc | bellard | goto fail;
|
194 | e80cfcfc | bellard | } |
195 | 420557e8 | bellard | close(fd); |
196 | 420557e8 | bellard | return size;
|
197 | 420557e8 | bellard | fail:
|
198 | 420557e8 | bellard | close(fd); |
199 | 420557e8 | bellard | return -1; |
200 | 420557e8 | bellard | } |