|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #include "ram.h"
1.1.1.2 root 8: #include "aout.h"
1.1.1.7 root 9: #include "autofd.h"
1.1.1.2 root 10: #include "elf.h"
11: #include "iodevstream.h"
12: #include "mainapp.h"
1.1.1.7 root 13: #include "mpu.h"
1.1.1.2 root 14: #include <fcntl.h>
15: #include <sys/stat.h>
16: #include <sys/mman.h>
17: #include <zlib.h>
1.1 root 18:
19: //
20: // メインメモリ
21: //
1.1.1.4 root 22:
23: std::unique_ptr<RAMDevice> gRAM;
24:
1.1 root 25: // RAM はロングワード単位でホストバイトオーダ配置なので、
26: // バイトアクセス、ワードアクセス時は HLB(), HLW() マクロを使用のこと。
1.1.1.8 ! root 27: std::unique_ptr<uint8[]> mainram;
1.1.1.4 root 28:
1.1 root 29: RAMDevice::RAMDevice()
30: {
31: logname = "ram";
32: devname = "MainRAM";
33: devaddr = 0;
34:
1.1.1.4 root 35: // アクセスウェイト
36: switch (gMainApp.GetVMType()) {
37: case VMTYPE_LUNA88K:
38: // 取扱説明書p.21 に、CMMU からのアクセスタイムが
39: // リード(4byte)で 200ns、バーストリード(16byte)で 320ns
40: // ライト(4byte)で 160ns、バーストライト(16byte)で 280ns とある。
41: // 25MHz は 40ns/clockで、この数値は CMMU からのアクセス全体の時間
42: // らしいので、ここで加算するウェイトはそれから 2クロック引いたもの。
43: read_wait = 3;
44: write_wait = 2;
45: break;
46: case VMTYPE_LUNA1:
47: // LUNA-I は1ウェイト。
48: read_wait = 1;
49: write_wait = 1;
50: break;
51:
52: case VMTYPE_X68030:
53: default:
54: // X68030 ではシステムポートが設定するのでここでは不要。
55: break;
56: }
1.1 root 57: }
58:
59: RAMDevice::~RAMDevice()
60: {
61: }
62:
63: bool
64: RAMDevice::Init()
65: {
1.1.1.4 root 66: int ram_size_MB;
67:
68: const ConfigItem& item = gConfig->Find("ram-size");
69: ram_size_MB = item.AsInt();
1.1.1.7 root 70: if (ram_size_MB < 1) {
1.1.1.3 root 71: item.Err();
72: return false;
1.1 root 73: }
1.1.1.7 root 74: // 下限以外の制約は機種による
75: switch (gMainApp.GetVMType()) {
76: case VMTYPE_X68030:
77: // メインメモリは 12MB まで。
78: // 内部は 8KB 単位で処理できるが設定が 1MB 単位。
79: if (ram_size_MB > 12) {
80: item.Err();
81: return false;
82: }
83: break;
84:
85: case VMTYPE_LUNA1:
86: // 16MB までは、実機に合わせて 4MB 単位とする。
87: // see http://wiki.netbsd.org/ports/luna68k/luna68k_info/#hardware
88: //
89: // 16MB を超える増設 (or 魔改造) 部分は 1MB 単位で 255MB までとする。
90: // 実 ROM のメモリチェックは 32KB だかそのくらいずつ行われ、
91: // 最後に番兵として Null 領域 (BusError ではなく) が必要。
92: // 現行の構成をあまり変えない範囲なら厳密には (256MB - 32KB) が
93: // 上限だが、設定ファイルからの指定が 1MB 単位なので 255MB。
94: if (ram_size_MB <= 16) {
95: if (ram_size_MB % 4 != 0) {
96: item.Err();
97: return false;
98: }
99: } else if (ram_size_MB > 255) {
100: item.Err();
101: return false;
102: }
103: break;
104:
105: case VMTYPE_LUNA88K:
106: // 64MB までは、実機に合わせて 16MB 単位とする。
107: //
108: // 64MB を超える増設 (or 魔改造) 部分は未確認。
109: if (ram_size_MB <= 64) {
110: if (ram_size_MB % 16 != 0) {
111: item.Err();
112: return false;
113: }
114: } else if (ram_size_MB > 255) {
115: item.Err();
116: return false;
117: }
118: break;
119:
120: default:
121: __unreachable();
122: }
1.1.1.3 root 123:
1.1.1.4 root 124: ram_size = ram_size_MB * 1024 * 1024;
1.1.1.8 ! root 125: mainram.reset(new uint8[ram_size]);
1.1 root 126:
1.1.1.7 root 127: // devtable[] への RAM デバイスの配置はこの後 VM::Init 側で行っている
128:
1.1 root 129: return true;
130: }
131:
1.1.1.8 ! root 132: bool
! 133: RAMDevice::PowerOn()
! 134: {
! 135: // XXX ノイズを用意する
! 136:
! 137: return true;
! 138: }
! 139:
1.1.1.4 root 140: void
141: RAMDevice::ResetHard()
142: {
143: // X68030 ではリセットで戻るはず。(LUNA は固定なので関係ない)
144: if (gMainApp.GetVMType() == VMTYPE_X68030) {
145: read_wait = 0;
146: write_wait = 0;
147: }
148: }
149:
1.1 root 150: uint64
151: RAMDevice::Read8(uint32 addr)
152: {
1.1.1.4 root 153: gMPU->AddCycle(read_wait);
1.1 root 154: uint32 data;
1.1.1.8 ! root 155: data = mainram[HLB(addr)];
1.1.1.6 root 156: putlog(4, "$%08x.B -> $%02x", addr, data);
1.1 root 157: return data;
158: }
159:
160: uint64
161: RAMDevice::Read16(uint32 addr)
162: {
1.1.1.4 root 163: gMPU->AddCycle(read_wait);
1.1 root 164: uint32 data;
1.1.1.8 ! root 165: data = *(uint16 *)&mainram[HLW(addr)];
1.1.1.6 root 166: putlog(4, "$%08x.W -> $%04x", addr, data);
1.1 root 167: return data;
168: }
169:
170: uint64
171: RAMDevice::Read32(uint32 addr)
172: {
1.1.1.4 root 173: gMPU->AddCycle(read_wait);
1.1 root 174: uint32 data;
1.1.1.8 ! root 175: data = *(uint32 *)&mainram[addr];
1.1.1.6 root 176: putlog(4, "$%08x.L -> $%08x", addr, data);
1.1 root 177: return data;
178: }
179:
180: uint64
181: RAMDevice::Write8(uint32 addr, uint32 data)
182: {
1.1.1.4 root 183: gMPU->AddCycle(write_wait);
1.1.1.8 ! root 184: mainram[HLB(addr)] = data;
1.1.1.6 root 185: putlog(3, "$%08x.B <- $%02x", addr, data);
1.1 root 186: return 0;
187: }
188:
189: uint64
190: RAMDevice::Write16(uint32 addr, uint32 data)
191: {
1.1.1.4 root 192: gMPU->AddCycle(write_wait);
1.1.1.8 ! root 193: *(uint16 *)&mainram[HLW(addr)] = data;
1.1.1.6 root 194: putlog(3, "$%08x.W <- $%04x", addr, data);
1.1 root 195: return 0;
196: }
197:
198: uint64
199: RAMDevice::Write32(uint32 addr, uint32 data)
200: {
1.1.1.4 root 201: gMPU->AddCycle(write_wait);
1.1.1.8 ! root 202: *(uint32 *)&mainram[addr] = data;
1.1.1.6 root 203: putlog(3, "$%08x.L <- $%08x", addr, data);
1.1 root 204: return 0;
205: }
206:
207: uint64
208: RAMDevice::Peek8(uint32 addr)
209: {
1.1.1.8 ! root 210: return mainram[HLB(addr)];
1.1 root 211: }
1.1.1.2 root 212:
1.1.1.4 root 213: // アクセスウェイトを設定 (X68030 でシステムポートから呼ばれる)
214: void
215: RAMDevice::SetWait(uint32 wait)
216: {
217: read_wait = wait;
218: write_wait = wait;
219: }
220:
1.1.1.2 root 221: // filepath で指定されるホストの実行ファイルをゲストにロードする。
222: // ファイルのフォーマットは自動で認識する。
223: // 戻り値はエントリポイントアドレス。エラーなら 0 を返す。
224: uint32
1.1.1.7 root 225: RAMDevice::LoadFile(const char *filepath)
1.1.1.2 root 226: {
227: uint8 *file;
228: struct stat st;
229: size_t filesize;
230: uint32 entry;
1.1.1.7 root 231: autofd fd;
1.1.1.2 root 232:
233: fd = open(filepath, O_RDONLY);
234: if (fd == -1) {
235: warn("LoadFile \"%s\" open failed", filepath);
236: return 0;
237: }
238:
239: if (fstat(fd, &st) == -1) {
240: warn("LoadFile \"%s\" fstat failed", filepath);
241: return 0;
242: }
243:
244: if (!S_ISREG(st.st_mode)) {
245: warnx("LoadFile \"%s\" not a regular file", filepath);
246: return 0;
247: }
248:
249: // 今の所マジック判定は最初の4バイトで出来るので
250: if (st.st_size < 4) {
251: warnx("LoadFile \"%s\" file too short", filepath);
252: return 0;
253: }
254: filesize = st.st_size;
255:
256: file = (uint8 *)mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
257: if (file == MAP_FAILED) {
258: warn("LoadFile \"%s\" mmap failed", filepath);
259: return 0;
260: }
261:
262: // 先頭3バイトの gzip マジックを調べる
263: if (file[0] == 0x1f && file[1] == 0x8b && file[2] == 0x08) {
264: // gzip
1.1.1.7 root 265: entry = LoadGzFile(filepath, file, filesize);
1.1.1.2 root 266: } else {
267: // 通常ファイル
1.1.1.7 root 268: entry = LoadFile(filepath, file, filesize);
1.1.1.2 root 269: }
270:
271: munmap(file, filesize);
272: return entry;
273: }
274:
275: // gzip を展開してゲストにロードする。
276: uint32
1.1.1.7 root 277: RAMDevice::LoadGzFile(const char *filepath, const uint8 *infile,
278: size_t infilesize)
1.1.1.2 root 279: {
280: z_stream z {};
281: uint32 decompsize;
282: int rv;
283:
284: // gzip なら(?) ファイルの末尾4バイトが (LE で?) 展開後サイズ(?)。
1.1.1.3 root 285: decompsize = le32toh(*(const uint32 *)&infile[infilesize - 4]);
1.1.1.2 root 286: std::unique_ptr<uint8[]> dstbuf(new uint8[decompsize]);
287:
288: // gzip 展開
289: // (uncompress() の方が楽そうに見えるが gzip 形式に対応してないらしい)
290: z.zalloc = Z_NULL;
291: z.zfree = Z_NULL;
292: z.opaque = Z_NULL;
293: rv = inflateInit2(&z, 47);
294: if (rv != Z_OK) {
295: warnx("LoadGzFile \"%s\" inflateInit2 failed %d", filepath, rv);
296: return 0;
297: }
298:
1.1.1.3 root 299: z.next_in = const_cast<Bytef *>(infile);
1.1.1.2 root 300: z.avail_in = infilesize - 4;
301: z.next_out = dstbuf.get();
302: z.avail_out = decompsize;
303: rv = inflate(&z, Z_NO_FLUSH);
304: if (rv != Z_OK) {
305: warnx("LoadGzFile \"%s\" inflate failed %d", filepath, rv);
306: return 0;
307: }
308:
309: inflateEnd(&z);
310:
311: // 展開できたのでロード
1.1.1.7 root 312: return LoadFile(filepath, dstbuf.get(), decompsize);
1.1.1.2 root 313: }
314:
315: // file, filesize で示されるバッファを実行ファイルとみなしてゲストにロードする。
316: // ファイルのフォーマットは自動で認識する。
317: // name はここではエラーメッセージとかの表示用でしかない。
318: // 戻り値はエントリポイントアドレス。エラーなら 0 を返す。
319: uint32
1.1.1.7 root 320: RAMDevice::LoadFile(const char *name, const uint8 *file, size_t filesize)
1.1.1.2 root 321: {
322: uint32 entry = 0;
323:
324: // フォーマットだけ判定して分岐
1.1.1.3 root 325: const Elf32_Ehdr *ehdr = (const Elf32_Ehdr *)file;
326: const aout_header *aout = (const aout_header *)file;
1.1.1.2 root 327: if (memcmp(ehdr->e_ident, "\177ELF", 4) == 0) {
1.1.1.7 root 328: entry = Load_elf32(name, file, filesize);
1.1.1.2 root 329: } else if ((be32toh(aout->magic) & 0xffff) == AOUT_OMAGIC) {
1.1.1.7 root 330: entry = Load_aout(name, file, filesize);
1.1.1.2 root 331: } else {
332: warnx("LoadFile \"%s\" unknown executable file format", name);
333: }
334:
335: return entry;
336: }
337:
338: // ホストの a.out をゲストの RAM に読み込む。
339: // 戻り値はエントリポイントアドレス。エラーなら 0 を返す。
340: uint32
1.1.1.7 root 341: RAMDevice::Load_aout(const char *name, const uint8 *file, size_t filesize)
1.1.1.2 root 342: {
343: aout_header aout;
344: int copylen;
345:
346: if (filesize < sizeof(aout)) {
347: warnx("Load_aout \"%s\" file too short", name);
348: return 0;
349: }
350:
351: // ヘッダを読み込む
352: // BigEndian しかターゲットにしてないので最初から全部変換しとく
1.1.1.3 root 353: aout.magic = be32toh(((const aout_header *)file)->magic);
354: aout.textsize = be32toh(((const aout_header *)file)->textsize);
355: aout.datasize = be32toh(((const aout_header *)file)->datasize);
356: aout.bsssize = be32toh(((const aout_header *)file)->bsssize);
357: aout.symsize = be32toh(((const aout_header *)file)->symsize);
358: aout.entry = be32toh(((const aout_header *)file)->entry);
359: aout.textrelsize = be32toh(((const aout_header *)file)->textrelsize);
360: aout.datarelsize = be32toh(((const aout_header *)file)->datarelsize);
1.1.1.2 root 361:
362: // マジックをチェック
1.1.1.7 root 363: uint32 target_mid;
364: if (gMainApp.HasVMFeature(VMF_M68K)) {
365: target_mid = AOUT_MID_M68K;
366: } else if (gMainApp.HasVMFeature(VMF_M88K)) {
367: target_mid = AOUT_MID_M88K;
368: } else {
369: PANIC("Unknown CPU?");
370: }
1.1.1.2 root 371: uint32 mid = AOUT_MID(aout.magic);
372: if (mid != target_mid) {
373: warnx("Load_aout \"%s\" machine id mismatch (%03x expected but %03x)",
374: name, target_mid, mid);
375: return 0;
376: }
377:
378: putmsg(1, "%s textsize = %08x", __func__, aout.textsize);
379: putmsg(1, "%s datasize = %08x", __func__, aout.datasize);
380: putmsg(1, "%s bsssize = %08x", __func__, aout.bsssize);
381: putmsg(1, "%s symsize = %08x", __func__, aout.symsize);
382: putmsg(1, "%s entry = %08x", __func__, aout.entry);
383: putmsg(1, "%s textrelsize = %08x", __func__, aout.textrelsize);
384: putmsg(1, "%s datarelsize = %08x", __func__, aout.datarelsize);
385:
386: // とりあえず再配置は無視
387: if (aout.textrelsize != 0 || aout.datarelsize != 0) {
388: warnx("Load_aout \"%s\" relocation not supported", name);
389: return 0;
390: }
391:
392: // OpenBSD の boot は text+data が filesize より大きくて何かおかしいが
393: // OMAGIC の a.out は text+data が連続しているだけなので、とりあえず
394: // 何も考えずにファイルサイズ分ロードしておく。
395: copylen = aout.textsize + aout.datasize;
396: if (copylen >= filesize) {
397: copylen = filesize;
1.1.1.8 ! root 398: warnx("warning: Load_aout \"%s\" corrupted? "
1.1.1.2 root 399: "(text=%u + data=%u, filesize=%d); loading %d bytes",
400: name, aout.textsize, aout.datasize, (int)filesize, copylen);
401: /* FALLTHROUGH */
402: }
403:
1.1.1.7 root 404: if (aout.entry + copylen > GetSize()) {
405: warnx("Load_aout \"%s\" out of memory in VM", name);
406: return 0;
407: }
408:
1.1.1.2 root 409: // 再配置不要なので、text + data を entry に置いて entry に飛ぶだけ
410: IODeviceStream ds(this, aout.entry);
411: const uint8 *src = file + sizeof(aout);
412: for (int i = 0; i < copylen; i++) {
413: ds.Write8(*src++);
414: }
415:
416: return aout.entry;
417: }
418:
419: // ELF フォーマットのエンディアンからホストエンディアンに変換
420: #define elf16toh(x) ((ehdr->e_ident[EI_DATA] == ELFDATA2MSB) ? \
421: be16toh(x) : le16toh(x))
422: #define elf32toh(x) ((ehdr->e_ident[EI_DATA] == ELFDATA2MSB) ? \
423: be32toh(x) : le32toh(x))
424:
1.1.1.5 root 425: // XXX このへん、そのうちきれいにする
426: #define GetElfStr1(array, v) GetElfStr(array, countof(array), v)
427: static const char *
428: GetElfStr(const std::pair<uint, const char *> *map, uint mapcount, uint v)
429: {
430: for (int i = 0; i < mapcount; i++) {
431: if (map[i].first == v) {
432: return map[i].second;
433: }
434: }
435: return "?";
436: }
437:
438: static std::pair<uint, const char *> class_str[] = {
439: { ELFCLASSNONE, "NONE" },
440: { ELFCLASS32, "32bit" },
441: { ELFCLASS64, "64bit" },
442: };
443: #define GetElfClassStr(x) GetElfStr1(class_str, (x))
444:
445: static std::pair<uint, const char *> data_str[] = {
446: { ELFDATANONE, "NONE" },
447: { ELFDATA2LSB, "LE" },
448: { ELFDATA2MSB, "BE" },
449: };
450: #define GetElfDataStr(x) GetElfStr1(data_str, (x))
451:
452: static std::pair<uint, const char *> etype_str[] = {
453: { ET_NONE, "ET_NONE" },
454: { ET_REL, "ET_REL" },
455: { ET_EXEC, "ET_EXEC" },
456: { ET_DYN, "ET_DYN" },
457: { ET_CORE, "ET_CORE" },
458: };
459: #define GetElfETypeStr(x) GetElfStr1(etype_str, (x))
460:
461: static std::pair<uint, const char *> machine_str[] = {
462: // 多いので関係分のみ
463: { EM_NONE, "NONE" },
464: { EM_68K, "Motorola 68000" },
465: { EM_88K, "Motorola 88000" },
466: };
467: #define GetElfMachineStr(x) GetElfStr1(machine_str, (x))
468:
469: static std::pair<uint, const char *> ptype_str[] = {
470: { PT_NULL, "PT_NULL" },
471: { PT_LOAD, "PT_LOAD" },
472: { PT_DYNAMIC, "PT_DYNAMIC" },
473: { PT_INTERP, "PT_INTERP" },
474: { PT_NOTE, "PT_NOTE" },
475: { PT_SHLIB, "PT_SHLIB" },
476: { PT_PHDR, "PT_PHDR" },
477: { PT_GNU_RELRO, "PT_GNU_RELRO" }, // GNU specific
478: { PT_OPENBSD_RANDOMIZE, "PT_OPENBSD_RANDOMIZE" },
479: { PT_OPENBSD_WXNEEDED, "PT_OPENBSD_WXNEEDED" },
480: { PT_OPENBSD_BOOTDATA, "PT_OPENBSD_BOOTDATA" },
481: };
482: #define GetElfPTypeStr(x) GetElfStr1(ptype_str, (x))
483:
1.1.1.2 root 484: // ホストの a.out をゲストの RAM に読み込む。
485: // 戻り値はエントリポイントアドレス。エラーなら 0 を返す。
486: uint32
1.1.1.7 root 487: RAMDevice::Load_elf32(const char *name, const uint8 *file, size_t filesize)
1.1.1.2 root 488: {
489: uint16 target_elf_mid;
490:
1.1.1.7 root 491: if (gMainApp.HasVMFeature(VMF_M68K)) {
1.1.1.2 root 492: target_elf_mid = EM_68K;
1.1.1.7 root 493: } else if (gMainApp.HasVMFeature(VMF_M88K)) {
1.1.1.2 root 494: target_elf_mid = EM_88K;
1.1.1.7 root 495: } else {
496: PANIC("Unknown CPU?");
1.1.1.2 root 497: }
498:
499: // ヘッダをチェック
500: const Elf32_Ehdr *ehdr = (const Elf32_Ehdr *)file;
501: if (filesize < sizeof(*ehdr)) {
502: warnx("Load_elf32 \"%s\" file too short", name);
503: return 0;
504: }
505: uint16 e_type = elf16toh(ehdr->e_type);
506: uint16 e_machine = elf16toh(ehdr->e_machine);
507: uint32 e_entry = elf32toh(ehdr->e_entry);
1.1.1.5 root 508: if (loglevel >= 1) {
509: uint n;
510: n = ehdr->e_ident[EI_CLASS];
1.1.1.7 root 511: putlogn("EI_CLASS = $%02x (%s)", n, GetElfClassStr(n));
1.1.1.5 root 512: n = ehdr->e_ident[EI_DATA];
1.1.1.7 root 513: putlogn("EI_DATA = $%02x (%s)", n, GetElfDataStr(n));
1.1.1.5 root 514:
1.1.1.7 root 515: putlogn("e_type = $%02x (%s)", e_type, GetElfETypeStr(e_type));
516: putlogn("e_machine = $%02x (%s)", e_machine,
1.1.1.5 root 517: GetElfMachineStr(e_machine));
1.1.1.7 root 518: putlogn("e_entry = $%08x", e_entry);
1.1.1.5 root 519: }
1.1.1.2 root 520:
521: if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
522: warnx("Load_elf32 \"%s\" not ELF32 format", name);
523: return 0;
524: }
525: if (e_type != ET_EXEC) {
526: warnx("Load_elf32 \"%s\" not executable file", name);
527: return 0;
528: }
529: if (e_machine != target_elf_mid) {
530: warnx("Load_elf32 \"%s\" machine type mismatch "
531: "($%02x expected but $%02x)",
532: name, target_elf_mid, e_machine);
533: return 0;
534: }
535:
536: // プログラムヘッダに読み込むべき領域が示されている
537: // phoff がプログラムヘッダのファイル先頭からのオフセット
538: // phentsize がプログラムヘッダ1つの大きさ
539: // phnum がプログラムヘッダの個数
540: uint32 e_phoff = elf32toh(ehdr->e_phoff);
541: uint16 e_phentsize = elf16toh(ehdr->e_phentsize);
542: uint16 e_phnum = elf16toh(ehdr->e_phnum);
1.1.1.5 root 543: if (loglevel >= 1) {
1.1.1.7 root 544: putlogn("e_phoff = $%08x", e_phoff);
545: putlogn("e_phentsize = $%04x", e_phentsize);
546: putlogn("e_phnum = %d", e_phnum);
1.1.1.5 root 547: }
1.1.1.2 root 548: if (e_phentsize != sizeof(Elf32_Phdr)) {
549: warnx("Load_elf32 \"%s\" unknown program header size 0x%x",
550: name, e_phentsize);
551: return 0;
552: }
553:
554: IODeviceStream ds(this);
555:
556: for (int j = 0; j < e_phnum; j++) {
557: const Elf32_Phdr *phdr = &((const Elf32_Phdr*)(file + e_phoff))[j];
558: // p_type が PT_LOAD なところをロードする。
559: // その際 p_memsz > p_filesz なら差が BSS 領域。
560: uint32 p_type = elf32toh(phdr->p_type); // タイプ
561: uint32 p_offset = elf32toh(phdr->p_offset); // ファイル上のオフセット
562: uint32 p_vaddr = elf32toh(phdr->p_vaddr); // 仮想アドレス
563: uint32 p_filesz = elf32toh(phdr->p_filesz); // 読み込み元ファイルサイズ
564: uint32 p_memsz = elf32toh(phdr->p_memsz); // 書き込み先サイズ
1.1.1.5 root 565: if (loglevel >= 1) {
1.1.1.7 root 566: putlogn("[%d] p_type = $%08x (%s)", j,
1.1.1.5 root 567: p_type, GetElfPTypeStr(p_type));
1.1.1.7 root 568: putlogn(" p_offset = $%08x", p_offset);
569: putlogn(" p_vaddr = $%08x", p_vaddr);
570: putlogn(" p_filesz = $%08x", p_filesz);
571: putlogn(" p_memsz = $%08x", p_memsz);
1.1.1.5 root 572: }
1.1.1.2 root 573:
574: if (p_type == PT_LOAD) {
1.1.1.7 root 575: if (p_vaddr + p_memsz > GetSize()) {
576: warn("Load_elf32 \"%s\" out of memory in VM", name);
577: return 0;
578: }
579:
1.1.1.2 root 580: ds.SetAddr(p_vaddr);
581: const uint8 *src = file + p_offset;
582: int i = 0;
583: for (; i < p_filesz; i++) {
584: ds.Write8(*src++);
585: }
586: for (; i < p_memsz; i++) {
587: ds.Write8(0);
588: }
1.1.1.5 root 589: } else if (p_type == PT_NOTE) {
590: // ベンダー文字列みたいなのらしいので無視してよい
591: continue;
592: } else if (p_type == PT_OPENBSD_RANDOMIZE) {
1.1.1.3 root 593: // XXX どうする?
594: continue;
595:
1.1.1.2 root 596: } else {
1.1.1.5 root 597: warnx("Load_elf32 \"%s\" p_type 0x%x(%s) not supported",
598: name, p_type, GetElfPTypeStr(p_type));
1.1.1.2 root 599: return 0;
600: }
601: }
602:
603: return e_entry;
604: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.