📄 gram.y
字号:
output = optarg; break; case 'a': architecture = optarg; break; case 'd': showparse = true; yy_flex_debug = 1; break; /* CPP OPTIONS */ case 'I': /* no spaces in what we hand to cpp: */ cpp_cmd_args << '-' << cc << App::BuildPath(optarg) << ' '; break; case 'D': case 'A': /* no spaces in what we hand to cpp: */ cpp_cmd_args << '-' << cc << optarg << ' '; break; case 'n': if (strcmp(optarg, "ostdinc") == 0) { use_std_inc_path = false; cpp_cmd_args << '-' << cc << optarg << ' '; } else if (strcmp(optarg, "ostddef") == 0) { use_std_def_list = false; cpp_cmd_args << '-' << cc << optarg << ' '; } else opterr++; break; default: opterr++; } } argc -= optind; argv += optind; if (argc > 1) opterr++;#if 0 if (argc == 0) opterr++;#endif if (output == 0) opterr++; if (!architecture) opterr++; if (opterr) Diag::fatal(1, "Usage: mkimage -a architecture -o output [-v] [-d] [-nostdinc] [-Idir]" " [-Ddef] [-Aassert] descrip_file\n"); ExecArch::Architecture arch = ExecArch::FromString(architecture); if (arch == ExecArch::arch_unknown) { Diag::fatal(1, "mkimage: unknown architecture \"%s\".\n", architecture.str()); } CurArch = architecture; if (use_std_def_list) /* std defines come first */ cpp_cmd << stddef; cpp_cmd << cpp_cmd_args; if (use_std_inc_path) /* std includes come last */ cpp_cmd << stdinc; cpp_cmd << " -include "; cpp_cmd << App::BuildPath("/eros/cross/include/mkimage.preinclude"); cpp_cmd << ' '; if (argc == 1) { current_file = App::BuildPath(argv[0]); cpp_cmd << current_file; } #if 0 fprintf(stderr, "Command to cpp is: %s\n", cpp_cmd.str());#endif yyin = popen(cpp_cmd.str(), "r"); if (!yyin) Diag::fatal(1, "Couldn't open description file\n"); if (verbose) App.SetInteractive(); yyparse(); if (num_errors == 0) image.WriteToFile(output); pclose(yyin); if (num_errors != 0u) App.SetExitValue(1u); App.Exit();}extern "C" { int yywrap();}intyywrap(){ return 1;}voidyyerror(const char * /* msg */){ Diag::printf("%s:%d: syntax error\n", current_file.str(), current_line); num_errors++;}boolAddRawSegment(ErosImage& image, InternedString fileName, DiskKey& segKey){ const char *source = fileName.str(); struct stat statbuf; int sfd = ::open(source, O_RDONLY); if (sfd < 0) { Diag::printf("Unable to open segment file \"%s\"\n", source); return false; } if (::fstat(sfd, &statbuf) < 0) { Diag::printf("Can't stat segment file \"%s\"\n", source); ::close(sfd); return false; } uint32_t nPages = statbuf.st_size / EROS_PAGE_SIZE; if (statbuf.st_size % EROS_PAGE_SIZE) nPages++; uint8_t *buf = new uint8_t[nPages * EROS_PAGE_SIZE]; memset(buf, 0, nPages * EROS_PAGE_SIZE); if (::read(sfd, buf, statbuf.st_size) != statbuf.st_size) { Diag::printf("Cannot read segment image \"%s\"\n", source); ::close(sfd); return false; } ::close(sfd); segKey = VoidDiskKey(); for (uint32_t pg = 0; pg < nPages; pg++) { uint32_t pageAddr = pg * EROS_PAGE_SIZE; DiskKey pageKey = image.AddDataPage(&buf[pg * EROS_PAGE_SIZE]); segKey = image.AddPageToSegment(segKey, pageAddr, pageKey); } return true;}boolAddZeroSegment(ErosImage& image, DiskKey& segKey, uint32_t nPages){ segKey = VoidDiskKey(); for (uint32_t pg = 0; pg < nPages; pg++) { uint32_t pageAddr = pg * EROS_PAGE_SIZE; DiskKey pageKey = image.AddZeroDataPage(); segKey = image.AddPageToSegment(segKey, pageAddr, pageKey); } return true;}boolAddEmptySegment(ErosImage& image, DiskKey& segKey, uint32_t nPages){ segKey = VoidDiskKey(); for (uint32_t pg = 0; pg < nPages; pg++) { uint32_t pageAddr = pg * EROS_PAGE_SIZE; VoidDiskKey voidKey; segKey = image.AddPageToSegment(segKey, pageAddr, voidKey); } return true;}boolGetProgramSymbolValue(InternedString fileName, InternedString symName, uint32_t& value){ ExecImage ei; if ( !ei.SetImage(fileName) ) return false; bool ok = ei.GetSymbolValue(symName, value);#if 0 Diag::printf("Value of \"%s\" in \"%s\" is 0x%08x\n" " entry pt is 0x%08x\n", symName.str(), fileName.str(), value, ei.EntryPt());#endif return ok;}/* This is by far the most complicated segment construction process. * The source of complexity is that both ELF and a.out (under suitable * conditions) will create one or more pages that are mapped at * multiple addresses. The common one is that the last page of code * and the first page of data are usually written in the same physical * page and multiply mapped. In truth, this is a pretty stupid thing * to do, since it allows the user to rewrite the last bit of the * code segment, but for the sake of compatibility we allow it. * * Processing is not as complicated as it looks. * * 1. For each unique page in the input file, we add a page to the * ErosImage file. * 2. For each MAPPING of a page in the input file, we add a page to * the segment. * * The end result is that we make another copy of everything in the * ExecImage file, which is arguably unfortunate, but much simpler * than the other approaches I've been able to come up with. Keep in * mind that the ExecImage instance is very temporary. * * The trick to this is that some pages either will not originate in * the binary file or will need to be duplicated */boolAddProgramSegment(ErosImage& image, InternedString fileName, DiskKey& segKey){ ExecImage ei; if ( !ei.SetImage(fileName) ) return false; const uint8_t* imageBuf = ei.GetImage(); segKey = VoidDiskKey(); DiskKey pageKey; PtrMap<DiskKey> map; /* Run through the regions in the executable image, finding all of * the associated pages and adding them to the ErosImage file at * most once (use the PtrMap to remember which pages we have seen). * Add these page keys to the segment at the appropriate address. * * Where the page is all zeros, there may be no corresponding page * in the exec image file. We assume that such pages are not * shared. * * Pages may be only partial in the exec image file. In that case * we zero-extend them. Such pages are copied into the ErosImage * exactly once. */ for (uint32_t i = 0; i < ei.NumRegions(); i++) { const ExecRegion& er = ei.GetRegion(i);#if 0 char perm[4] = "\0\0\0"; char *pbuf = perm; if (er.perm & ExecRegion::ER_R) *pbuf++ = 'R'; if (er.perm & ExecRegion::ER_W) *pbuf++ = 'W'; if (er.perm & ExecRegion::ER_X) *pbuf++ = 'X'; Diag::printf("va=0x%08x memsz=0x%08x filesz=0x%08x" " offset=0x%08x %s\n", er.vaddr, er.memsz, er.filesz, er.offset, perm);#endif uint32_t topfileva = er.vaddr + er.filesz; uint32_t topva = er.vaddr + er.memsz; uint32_t startva = er.vaddr & ~EROS_PAGE_MASK; uint32_t startoffset = er.offset; bool readOnly = false; /* In case not a paged image, back up the offset to the page boundary. Note that contrary to previous assumptions, the VA and the offset will not be congruent mod page size UNLESS the image is marked as paged. */ if (startva != er.vaddr) startoffset -= (er.vaddr - startva); if ((er.perm & ExecRegion::ER_W) == 0) readOnly = true; for (uint32_t va = startva; va < topva; va += EROS_PAGE_SIZE) { if (va >= topfileva) { /* Page has no image in the exec image file. Add a zero page: */#if 0 /* FIX: figure out someday why this occurs! */ if (er.perm & ExecRegion::ER_X) Diag::printf("WARNING: executable zero page\n");#endif pageKey = image.AddZeroDataPage(readOnly); } else { /* Page has image in the exec image file. See if we have * already copied this page into the domain image before we * copy it again: */ uint32_t offset = startoffset + (va - startva); if (map.Lookup(imageBuf + offset, pageKey)) { /* We have a page key, but it's read-only attribute may be * incorrect for this mapping, so adjust it: */ if (readOnly) pageKey.SetReadOnly(); } else { uint8_t pagebuf[EROS_PAGE_SIZE]; bzero((void *) pagebuf, EROS_PAGE_SIZE); uint32_t sz = EROS_PAGE_SIZE; if (topfileva - va < EROS_PAGE_SIZE) sz = (topfileva - va); memcpy(pagebuf, imageBuf + offset, sz); pageKey = image.AddDataPage(pagebuf, readOnly); } } segKey = image.AddPageToSegment(segKey, va, pageKey); } } if (segKey.IsVoidKey()) { Diag::error(1, "File \"%s\" has no pages.\n", fileName.str()); return false; } return true;}voidShowImageDirectory(const ErosImage& image){ Diag::printf("Image directory:\n"); for (uint32_t i = 0; i < image.nDirEnt; i++) { ErosImage::Directory d = image.GetDirEnt(i); Diag::printf(" [%2d]", i); Diag::printf(" %-16s ", image.GetString(d.name).str()); PrintDiskKey(d.key); Diag::printf("\n"); }}voidShowImageThreadDirectory(const ErosImage& image){ Diag::printf("Image threads:\n"); for (uint32_t i = 0; i < image.nStartups; i++) { ErosImage::Directory d = image.GetStartupEnt(i); Diag::printf(" [%2d]", i); Diag::printf(" %-16s ", image.GetString(d.name).str()); PrintDiskKey(d.key); Diag::printf("\n"); }}#define __EROS_PRIMARY_KEYDEF(name) { #name, (KT_##name >= FIRST_MISC_KEYTYPE) },/* OLD_MISCKEY(name) { #name, 0 }, */static const struct { char *name; int isValid;} KeyNames[KT_NUM_KEYTYPE] = {#include <eros/StdKeyType.h>};boolGetMiscKeyType(InternedString s, uint32_t& ty){ const char *sstr = s.str(); for (uint32_t i = 0; i < KT_NUM_KEYTYPE; i++) { if (strcasecmp(sstr, KeyNames[i].name) == 0) { if (KeyNames[i].isValid == 0) return false; ty = i; return true; } } return false;}uint16_tdecimal_value(char c){ /* also suitable for octal, binary */ return c - '0';}uint16_thex_value(char c){ if (isdigit(c)) return c - '0'; /* else it's a hex alpha */ return tolower(c) - 'a' + 10;}#ifdef KT_Wrapperuint32_tCalcWrapperRestriction(DiskKey segKey, uint32_t slot){ if (slot == WrapperFormat) return RESTRICT_NUMBER; DiskKey fmtKey = image.GetNodeSlot(segKey, WrapperFormat); if (slot == 0 || slot == WrapperSpace || slot == WrapperBackground) return RESTRICT_SEGMODE; if (slot == WrapperKeeper) return RESTRICT_START; return RESTRICT_VOID;}#else/* FIX: Should this honor the reserved slot counts? */uint32_tCalcRedSegRestriction(DiskKey segKey, uint32_t slot){ if (slot == RedSegFormat) return RESTRICT_NUMBER; DiskKey fmtKey = image.GetNodeSlot(segKey, RedSegFormat); if (slot < REDSEG_GET_INITIAL_SLOTS(fmtKey.nk)) return RESTRICT_SEGMODE; if (slot == REDSEG_GET_KPR_SLOT(fmtKey.nk)) return RESTRICT_START; if (slot == REDSEG_GET_BG_SLOT(fmtKey.nk)) return RESTRICT_SEGMODE; return RESTRICT_VOID;}#endifboolCheckRestriction(uint32_t restriction, DiskKey key){ if ((restriction & RESTRICT_VOID) && !key.IsVoidKey()) return false; if ((restriction & RESTRICT_NUMBER) && !key.IsType(KT_Number)) return false; if ((restriction & RESTRICT_SCHED) && !key.IsType(KT_Sched)) return false; if ((restriction & RESTRICT_IOSPACE) && !key.IsType(KT_DevicePrivs)) return false; if ((restriction & RESTRICT_START) && !key.IsType(KT_Start) && !key.IsVoidKey()) return false; if ((restriction & RESTRICT_SEGMODE) && ! (key.IsSegModeType() || key.IsType(KT_Number))) return false; if ((restriction & (RESTRICT_KEYREGS | RESTRICT_GENREGS)) && !key.IsType(KT_Node)) return false; return true;}/* ???APPLIES the qualifications specified by qualifier to the key. */boolQualifyKey(uint32_t qualifier, DiskKey key, DiskKey& out){ if (qualifier & ATTRIB_WEAK) { switch(key.GetType()) { case KT_Node: case KT_Segment: key.SetWeak(); break; case KT_Number: /* don't whine about these */ case KT_Page: break; default: Diag::printf("%s:%d: WEAK qualifier not permitted" " for key type\n", current_file.str(), current_line); return false; } } if (qualifier & ATTRIB_RO) { switch(key.GetType()) { case KT_Node: case KT_Page: case KT_Segment: key.SetReadOnly(); break; case KT_Number: /* don't whine about these */ break; default: Diag::printf("%s:%d: RO qualifier not permitted" " for key type\n", current_file.str(), current_line); return false; } } if (qualifier & ATTRIB_NC) { switch(key.GetType()) { case KT_Node: case KT_Segment: key.SetNoCall(); break; case KT_Number: /* don't whine about these */ case KT_Page: break; default: Diag::printf("%s:%d: NC qualifier not permitted" " for key type\n", current_file.str(), current_line); return false; } } out = key; return true;}DiskKey NumberFromString(InternedString& is){ char theText[12]; bzero(theText, 12); strncpy(theText, is.str(), 12); uint32_t w0 = ( ((uint32_t) theText[3]) << 24 | ((uint32_t) theText[2]) << 16 | ((uint32_t) theText[1]) << 8 | ((uint32_t) theText[0]) ); uint32_t w1 = ( ((uint32_t) theText[7]) << 24 | ((uint32_t) theText[6]) << 16 | ((uint32_t) theText[5]) << 8 | ((uint32_t) theText[4]) ); uint32_t w2 = ( ((uint32_t) theText[11]) << 24 | ((uint32_t) theText[10]) << 16 | ((uint32_t) theText[9]) << 8 | ((uint32_t) theText[8]) ); return NumberKey(w0, w1, w2);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -