Annotation of nono/vm/ram.cpp, revision 1.1.1.6

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.