|
|
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.2 root 27: std::unique_ptr<uint8[]> ram;
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.2 root 125: ram.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.4 root 132: void
133: RAMDevice::ResetHard()
134: {
135: // X68030 ではリセットで戻るはず。(LUNA は固定なので関係ない)
136: if (gMainApp.GetVMType() == VMTYPE_X68030) {
137: read_wait = 0;
138: write_wait = 0;
139: }
140: }
141:
1.1 root 142: uint64
143: RAMDevice::Read8(uint32 addr)
144: {
1.1.1.4 root 145: gMPU->AddCycle(read_wait);
1.1 root 146: uint32 data;
147: data = ram[HLB(addr)];
1.1.1.6 root 148: putlog(4, "$%08x.B -> $%02x", addr, data);
1.1 root 149: return data;
150: }
151:
152: uint64
153: RAMDevice::Read16(uint32 addr)
154: {
1.1.1.4 root 155: gMPU->AddCycle(read_wait);
1.1 root 156: uint32 data;
157: data = *(uint16 *)&ram[HLW(addr)];
1.1.1.6 root 158: putlog(4, "$%08x.W -> $%04x", addr, data);
1.1 root 159: return data;
160: }
161:
162: uint64
163: RAMDevice::Read32(uint32 addr)
164: {
1.1.1.4 root 165: gMPU->AddCycle(read_wait);
1.1 root 166: uint32 data;
167: data = *(uint32 *)&ram[addr];
1.1.1.6 root 168: putlog(4, "$%08x.L -> $%08x", addr, data);
1.1 root 169: return data;
170: }
171:
172: uint64
173: RAMDevice::Write8(uint32 addr, uint32 data)
174: {
1.1.1.4 root 175: gMPU->AddCycle(write_wait);
1.1 root 176: ram[HLB(addr)] = data;
1.1.1.6 root 177: putlog(3, "$%08x.B <- $%02x", addr, data);
1.1 root 178: return 0;
179: }
180:
181: uint64
182: RAMDevice::Write16(uint32 addr, uint32 data)
183: {
1.1.1.4 root 184: gMPU->AddCycle(write_wait);
1.1 root 185: *(uint16 *)&ram[HLW(addr)] = data;
1.1.1.6 root 186: putlog(3, "$%08x.W <- $%04x", addr, data);
1.1 root 187: return 0;
188: }
189:
190: uint64
191: RAMDevice::Write32(uint32 addr, uint32 data)
192: {
1.1.1.4 root 193: gMPU->AddCycle(write_wait);
1.1 root 194: *(uint32 *)&ram[addr] = data;
1.1.1.6 root 195: putlog(3, "$%08x.L <- $%08x", addr, data);
1.1 root 196: return 0;
197: }
198:
199: uint64
200: RAMDevice::Peek8(uint32 addr)
201: {
202: return ram[HLB(addr)];
203: }
1.1.1.2 root 204:
1.1.1.4 root 205: // アクセスウェイトを設定 (X68030 でシステムポートから呼ばれる)
206: void
207: RAMDevice::SetWait(uint32 wait)
208: {
209: read_wait = wait;
210: write_wait = wait;
211: }
212:
1.1.1.2 root 213: // filepath で指定されるホストの実行ファイルをゲストにロードする。
214: // ファイルのフォーマットは自動で認識する。
215: // 戻り値はエントリポイントアドレス。エラーなら 0 を返す。
216: uint32
1.1.1.7 ! root 217: RAMDevice::LoadFile(const char *filepath)
1.1.1.2 root 218: {
219: uint8 *file;
220: struct stat st;
221: size_t filesize;
222: uint32 entry;
1.1.1.7 ! root 223: autofd fd;
1.1.1.2 root 224:
225: fd = open(filepath, O_RDONLY);
226: if (fd == -1) {
227: warn("LoadFile \"%s\" open failed", filepath);
228: return 0;
229: }
230:
231: if (fstat(fd, &st) == -1) {
232: warn("LoadFile \"%s\" fstat failed", filepath);
233: return 0;
234: }
235:
236: if (!S_ISREG(st.st_mode)) {
237: warnx("LoadFile \"%s\" not a regular file", filepath);
238: return 0;
239: }
240:
241: // 今の所マジック判定は最初の4バイトで出来るので
242: if (st.st_size < 4) {
243: warnx("LoadFile \"%s\" file too short", filepath);
244: return 0;
245: }
246: filesize = st.st_size;
247:
248: file = (uint8 *)mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
249: if (file == MAP_FAILED) {
250: warn("LoadFile \"%s\" mmap failed", filepath);
251: return 0;
252: }
253:
254: // 先頭3バイトの gzip マジックを調べる
255: if (file[0] == 0x1f && file[1] == 0x8b && file[2] == 0x08) {
256: // gzip
1.1.1.7 ! root 257: entry = LoadGzFile(filepath, file, filesize);
1.1.1.2 root 258: } else {
259: // 通常ファイル
1.1.1.7 ! root 260: entry = LoadFile(filepath, file, filesize);
1.1.1.2 root 261: }
262:
263: munmap(file, filesize);
264: return entry;
265: }
266:
267: // gzip を展開してゲストにロードする。
268: uint32
1.1.1.7 ! root 269: RAMDevice::LoadGzFile(const char *filepath, const uint8 *infile,
! 270: size_t infilesize)
1.1.1.2 root 271: {
272: z_stream z {};
273: uint32 decompsize;
274: int rv;
275:
276: // gzip なら(?) ファイルの末尾4バイトが (LE で?) 展開後サイズ(?)。
1.1.1.3 root 277: decompsize = le32toh(*(const uint32 *)&infile[infilesize - 4]);
1.1.1.2 root 278: std::unique_ptr<uint8[]> dstbuf(new uint8[decompsize]);
279:
280: // gzip 展開
281: // (uncompress() の方が楽そうに見えるが gzip 形式に対応してないらしい)
282: z.zalloc = Z_NULL;
283: z.zfree = Z_NULL;
284: z.opaque = Z_NULL;
285: rv = inflateInit2(&z, 47);
286: if (rv != Z_OK) {
287: warnx("LoadGzFile \"%s\" inflateInit2 failed %d", filepath, rv);
288: return 0;
289: }
290:
1.1.1.3 root 291: z.next_in = const_cast<Bytef *>(infile);
1.1.1.2 root 292: z.avail_in = infilesize - 4;
293: z.next_out = dstbuf.get();
294: z.avail_out = decompsize;
295: rv = inflate(&z, Z_NO_FLUSH);
296: if (rv != Z_OK) {
297: warnx("LoadGzFile \"%s\" inflate failed %d", filepath, rv);
298: return 0;
299: }
300:
301: inflateEnd(&z);
302:
303: // 展開できたのでロード
1.1.1.7 ! root 304: return LoadFile(filepath, dstbuf.get(), decompsize);
1.1.1.2 root 305: }
306:
307: // file, filesize で示されるバッファを実行ファイルとみなしてゲストにロードする。
308: // ファイルのフォーマットは自動で認識する。
309: // name はここではエラーメッセージとかの表示用でしかない。
310: // 戻り値はエントリポイントアドレス。エラーなら 0 を返す。
311: uint32
1.1.1.7 ! root 312: RAMDevice::LoadFile(const char *name, const uint8 *file, size_t filesize)
1.1.1.2 root 313: {
314: uint32 entry = 0;
315:
316: // フォーマットだけ判定して分岐
1.1.1.3 root 317: const Elf32_Ehdr *ehdr = (const Elf32_Ehdr *)file;
318: const aout_header *aout = (const aout_header *)file;
1.1.1.2 root 319: if (memcmp(ehdr->e_ident, "\177ELF", 4) == 0) {
1.1.1.7 ! root 320: entry = Load_elf32(name, file, filesize);
1.1.1.2 root 321: } else if ((be32toh(aout->magic) & 0xffff) == AOUT_OMAGIC) {
1.1.1.7 ! root 322: entry = Load_aout(name, file, filesize);
1.1.1.2 root 323: } else {
324: warnx("LoadFile \"%s\" unknown executable file format", name);
325: }
326:
327: return entry;
328: }
329:
330: // ホストの a.out をゲストの RAM に読み込む。
331: // 戻り値はエントリポイントアドレス。エラーなら 0 を返す。
332: uint32
1.1.1.7 ! root 333: RAMDevice::Load_aout(const char *name, const uint8 *file, size_t filesize)
1.1.1.2 root 334: {
335: aout_header aout;
336: int copylen;
337:
338: if (filesize < sizeof(aout)) {
339: warnx("Load_aout \"%s\" file too short", name);
340: return 0;
341: }
342:
343: // ヘッダを読み込む
344: // BigEndian しかターゲットにしてないので最初から全部変換しとく
1.1.1.3 root 345: aout.magic = be32toh(((const aout_header *)file)->magic);
346: aout.textsize = be32toh(((const aout_header *)file)->textsize);
347: aout.datasize = be32toh(((const aout_header *)file)->datasize);
348: aout.bsssize = be32toh(((const aout_header *)file)->bsssize);
349: aout.symsize = be32toh(((const aout_header *)file)->symsize);
350: aout.entry = be32toh(((const aout_header *)file)->entry);
351: aout.textrelsize = be32toh(((const aout_header *)file)->textrelsize);
352: aout.datarelsize = be32toh(((const aout_header *)file)->datarelsize);
1.1.1.2 root 353:
354: // マジックをチェック
1.1.1.7 ! root 355: uint32 target_mid;
! 356: if (gMainApp.HasVMFeature(VMF_M68K)) {
! 357: target_mid = AOUT_MID_M68K;
! 358: } else if (gMainApp.HasVMFeature(VMF_M88K)) {
! 359: target_mid = AOUT_MID_M88K;
! 360: } else {
! 361: PANIC("Unknown CPU?");
! 362: }
1.1.1.2 root 363: uint32 mid = AOUT_MID(aout.magic);
364: if (mid != target_mid) {
365: warnx("Load_aout \"%s\" machine id mismatch (%03x expected but %03x)",
366: name, target_mid, mid);
367: return 0;
368: }
369:
370: putmsg(1, "%s textsize = %08x", __func__, aout.textsize);
371: putmsg(1, "%s datasize = %08x", __func__, aout.datasize);
372: putmsg(1, "%s bsssize = %08x", __func__, aout.bsssize);
373: putmsg(1, "%s symsize = %08x", __func__, aout.symsize);
374: putmsg(1, "%s entry = %08x", __func__, aout.entry);
375: putmsg(1, "%s textrelsize = %08x", __func__, aout.textrelsize);
376: putmsg(1, "%s datarelsize = %08x", __func__, aout.datarelsize);
377:
378: // とりあえず再配置は無視
379: if (aout.textrelsize != 0 || aout.datarelsize != 0) {
380: warnx("Load_aout \"%s\" relocation not supported", name);
381: return 0;
382: }
383:
384: // OpenBSD の boot は text+data が filesize より大きくて何かおかしいが
385: // OMAGIC の a.out は text+data が連続しているだけなので、とりあえず
386: // 何も考えずにファイルサイズ分ロードしておく。
387: copylen = aout.textsize + aout.datasize;
388: if (copylen >= filesize) {
389: copylen = filesize;
390: warnx("warning: Load_aout \"%s\" coruppted? "
391: "(text=%u + data=%u, filesize=%d); loading %d bytes",
392: name, aout.textsize, aout.datasize, (int)filesize, copylen);
393: /* FALLTHROUGH */
394: }
395:
1.1.1.7 ! root 396: if (aout.entry + copylen > GetSize()) {
! 397: warnx("Load_aout \"%s\" out of memory in VM", name);
! 398: return 0;
! 399: }
! 400:
1.1.1.2 root 401: // 再配置不要なので、text + data を entry に置いて entry に飛ぶだけ
402: IODeviceStream ds(this, aout.entry);
403: const uint8 *src = file + sizeof(aout);
404: for (int i = 0; i < copylen; i++) {
405: ds.Write8(*src++);
406: }
407:
408: return aout.entry;
409: }
410:
411: // ELF フォーマットのエンディアンからホストエンディアンに変換
412: #define elf16toh(x) ((ehdr->e_ident[EI_DATA] == ELFDATA2MSB) ? \
413: be16toh(x) : le16toh(x))
414: #define elf32toh(x) ((ehdr->e_ident[EI_DATA] == ELFDATA2MSB) ? \
415: be32toh(x) : le32toh(x))
416:
1.1.1.5 root 417: // XXX このへん、そのうちきれいにする
418: #define GetElfStr1(array, v) GetElfStr(array, countof(array), v)
419: static const char *
420: GetElfStr(const std::pair<uint, const char *> *map, uint mapcount, uint v)
421: {
422: for (int i = 0; i < mapcount; i++) {
423: if (map[i].first == v) {
424: return map[i].second;
425: }
426: }
427: return "?";
428: }
429:
430: static std::pair<uint, const char *> class_str[] = {
431: { ELFCLASSNONE, "NONE" },
432: { ELFCLASS32, "32bit" },
433: { ELFCLASS64, "64bit" },
434: };
435: #define GetElfClassStr(x) GetElfStr1(class_str, (x))
436:
437: static std::pair<uint, const char *> data_str[] = {
438: { ELFDATANONE, "NONE" },
439: { ELFDATA2LSB, "LE" },
440: { ELFDATA2MSB, "BE" },
441: };
442: #define GetElfDataStr(x) GetElfStr1(data_str, (x))
443:
444: static std::pair<uint, const char *> etype_str[] = {
445: { ET_NONE, "ET_NONE" },
446: { ET_REL, "ET_REL" },
447: { ET_EXEC, "ET_EXEC" },
448: { ET_DYN, "ET_DYN" },
449: { ET_CORE, "ET_CORE" },
450: };
451: #define GetElfETypeStr(x) GetElfStr1(etype_str, (x))
452:
453: static std::pair<uint, const char *> machine_str[] = {
454: // 多いので関係分のみ
455: { EM_NONE, "NONE" },
456: { EM_68K, "Motorola 68000" },
457: { EM_88K, "Motorola 88000" },
458: };
459: #define GetElfMachineStr(x) GetElfStr1(machine_str, (x))
460:
461: static std::pair<uint, const char *> ptype_str[] = {
462: { PT_NULL, "PT_NULL" },
463: { PT_LOAD, "PT_LOAD" },
464: { PT_DYNAMIC, "PT_DYNAMIC" },
465: { PT_INTERP, "PT_INTERP" },
466: { PT_NOTE, "PT_NOTE" },
467: { PT_SHLIB, "PT_SHLIB" },
468: { PT_PHDR, "PT_PHDR" },
469: { PT_GNU_RELRO, "PT_GNU_RELRO" }, // GNU specific
470: { PT_OPENBSD_RANDOMIZE, "PT_OPENBSD_RANDOMIZE" },
471: { PT_OPENBSD_WXNEEDED, "PT_OPENBSD_WXNEEDED" },
472: { PT_OPENBSD_BOOTDATA, "PT_OPENBSD_BOOTDATA" },
473: };
474: #define GetElfPTypeStr(x) GetElfStr1(ptype_str, (x))
475:
1.1.1.2 root 476: // ホストの a.out をゲストの RAM に読み込む。
477: // 戻り値はエントリポイントアドレス。エラーなら 0 を返す。
478: uint32
1.1.1.7 ! root 479: RAMDevice::Load_elf32(const char *name, const uint8 *file, size_t filesize)
1.1.1.2 root 480: {
481: uint16 target_elf_mid;
482:
1.1.1.7 ! root 483: if (gMainApp.HasVMFeature(VMF_M68K)) {
1.1.1.2 root 484: target_elf_mid = EM_68K;
1.1.1.7 ! root 485: } else if (gMainApp.HasVMFeature(VMF_M88K)) {
1.1.1.2 root 486: target_elf_mid = EM_88K;
1.1.1.7 ! root 487: } else {
! 488: PANIC("Unknown CPU?");
1.1.1.2 root 489: }
490:
491: // ヘッダをチェック
492: const Elf32_Ehdr *ehdr = (const Elf32_Ehdr *)file;
493: if (filesize < sizeof(*ehdr)) {
494: warnx("Load_elf32 \"%s\" file too short", name);
495: return 0;
496: }
497: uint16 e_type = elf16toh(ehdr->e_type);
498: uint16 e_machine = elf16toh(ehdr->e_machine);
499: uint32 e_entry = elf32toh(ehdr->e_entry);
1.1.1.5 root 500: if (loglevel >= 1) {
501: uint n;
502: n = ehdr->e_ident[EI_CLASS];
1.1.1.7 ! root 503: putlogn("EI_CLASS = $%02x (%s)", n, GetElfClassStr(n));
1.1.1.5 root 504: n = ehdr->e_ident[EI_DATA];
1.1.1.7 ! root 505: putlogn("EI_DATA = $%02x (%s)", n, GetElfDataStr(n));
1.1.1.5 root 506:
1.1.1.7 ! root 507: putlogn("e_type = $%02x (%s)", e_type, GetElfETypeStr(e_type));
! 508: putlogn("e_machine = $%02x (%s)", e_machine,
1.1.1.5 root 509: GetElfMachineStr(e_machine));
1.1.1.7 ! root 510: putlogn("e_entry = $%08x", e_entry);
1.1.1.5 root 511: }
1.1.1.2 root 512:
513: if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
514: warnx("Load_elf32 \"%s\" not ELF32 format", name);
515: return 0;
516: }
517: if (e_type != ET_EXEC) {
518: warnx("Load_elf32 \"%s\" not executable file", name);
519: return 0;
520: }
521: if (e_machine != target_elf_mid) {
522: warnx("Load_elf32 \"%s\" machine type mismatch "
523: "($%02x expected but $%02x)",
524: name, target_elf_mid, e_machine);
525: return 0;
526: }
527:
528: // プログラムヘッダに読み込むべき領域が示されている
529: // phoff がプログラムヘッダのファイル先頭からのオフセット
530: // phentsize がプログラムヘッダ1つの大きさ
531: // phnum がプログラムヘッダの個数
532: uint32 e_phoff = elf32toh(ehdr->e_phoff);
533: uint16 e_phentsize = elf16toh(ehdr->e_phentsize);
534: uint16 e_phnum = elf16toh(ehdr->e_phnum);
1.1.1.5 root 535: if (loglevel >= 1) {
1.1.1.7 ! root 536: putlogn("e_phoff = $%08x", e_phoff);
! 537: putlogn("e_phentsize = $%04x", e_phentsize);
! 538: putlogn("e_phnum = %d", e_phnum);
1.1.1.5 root 539: }
1.1.1.2 root 540: if (e_phentsize != sizeof(Elf32_Phdr)) {
541: warnx("Load_elf32 \"%s\" unknown program header size 0x%x",
542: name, e_phentsize);
543: return 0;
544: }
545:
546: IODeviceStream ds(this);
547:
548: for (int j = 0; j < e_phnum; j++) {
549: const Elf32_Phdr *phdr = &((const Elf32_Phdr*)(file + e_phoff))[j];
550: // p_type が PT_LOAD なところをロードする。
551: // その際 p_memsz > p_filesz なら差が BSS 領域。
552: uint32 p_type = elf32toh(phdr->p_type); // タイプ
553: uint32 p_offset = elf32toh(phdr->p_offset); // ファイル上のオフセット
554: uint32 p_vaddr = elf32toh(phdr->p_vaddr); // 仮想アドレス
555: uint32 p_filesz = elf32toh(phdr->p_filesz); // 読み込み元ファイルサイズ
556: uint32 p_memsz = elf32toh(phdr->p_memsz); // 書き込み先サイズ
1.1.1.5 root 557: if (loglevel >= 1) {
1.1.1.7 ! root 558: putlogn("[%d] p_type = $%08x (%s)", j,
1.1.1.5 root 559: p_type, GetElfPTypeStr(p_type));
1.1.1.7 ! root 560: putlogn(" p_offset = $%08x", p_offset);
! 561: putlogn(" p_vaddr = $%08x", p_vaddr);
! 562: putlogn(" p_filesz = $%08x", p_filesz);
! 563: putlogn(" p_memsz = $%08x", p_memsz);
1.1.1.5 root 564: }
1.1.1.2 root 565:
566: if (p_type == PT_LOAD) {
1.1.1.7 ! root 567: if (p_vaddr + p_memsz > GetSize()) {
! 568: warn("Load_elf32 \"%s\" out of memory in VM", name);
! 569: return 0;
! 570: }
! 571:
1.1.1.2 root 572: ds.SetAddr(p_vaddr);
573: const uint8 *src = file + p_offset;
574: int i = 0;
575: for (; i < p_filesz; i++) {
576: ds.Write8(*src++);
577: }
578: for (; i < p_memsz; i++) {
579: ds.Write8(0);
580: }
1.1.1.5 root 581: } else if (p_type == PT_NOTE) {
582: // ベンダー文字列みたいなのらしいので無視してよい
583: continue;
584: } else if (p_type == PT_OPENBSD_RANDOMIZE) {
1.1.1.3 root 585: // XXX どうする?
586: continue;
587:
1.1.1.2 root 588: } else {
1.1.1.5 root 589: warnx("Load_elf32 \"%s\" p_type 0x%x(%s) not supported",
590: name, p_type, GetElfPTypeStr(p_type));
1.1.1.2 root 591: return 0;
592: }
593: }
594:
595: return e_entry;
596: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.