void MachoExport::writeSymbol(const char *symbolName, unsigned char nType, unsigned char nSect, unsigned long offset) { #if (SIZEOF_VOIDP == 8) struct nlist_64 symbol; #else struct nlist symbol; #endif memset(&symbol, 0, sizeof(symbol)); // Zero unused fields symbol.n_un.n_strx = stringTable.makeEntry(symbolName); symbol.n_type = nType; symbol.n_sect = nSect+1; // Sections count from 1. symbol.n_desc = REFERENCE_FLAG_DEFINED; adjustOffset(nSect, offset); symbol.n_value = offset; fwrite(&symbol, sizeof(symbol), 1, exportFile); symbolCount++; }
void CommentableObjectViewer::renderPosts(shared_ptr<XMLPortalExporter> exporter) { if(getObject() == nullptr || getObject()->allowChild(portalObjectTypePost) == false) return; // Calcola il numero totale di posts uint32 total_posts = getEntity()->getChildsCount(getDatabase(), portalObjectTypePost); if(total_posts == 0) return; // Numero di posts da visualizzare per pagina uint32 posts_to_show = getSkin()->getPagerItems(); // Inizializza l'offset di estrazione uint32 offset = conversions::from_utf16<uint32>(getRequest()->getUrlParam(OS_URL_PARAM_OFFSET)); // Corregge l'offset se necessario adjustOffset(total_posts, posts_to_show, offset); objects_posts_list posts; // Estrae le risposte nell'intervallo richiesto shared_ptr<EntitiesEntities> post_childs = getEntity()->getChilds(getDatabase(), portalObjectTypePost, RangeUint32(offset, posts_to_show)); for(EntitiesEntities::iterator i = post_childs->begin(); i != post_childs->end(); ++i) { // Carica la riposta corrente shared_ptr<EntitiesEntity> post_entity = post_childs->get(getDatabase(), *i); if(post_entity != nullptr) { // Calcola la revisione corrente della risposta shared_ptr<ObjectsPost> current_post = objects_post_cast(post_entity->getCurrent()); if(current_post != nullptr) posts.push_back(current_post); } } if(posts.empty() == false) { shared_ptr<XMLNode> posts_node = exporter->getNode(OS_PORTAL_OBJECT_POST_GROUPNAME); for(objects_posts_list::const_iterator i = posts.begin(); i != posts.end(); ++i) { shared_ptr<XMLPortalExporter> postExporter(OS_NEW XMLPortalExporter(posts_node->addChild(OS_PORTAL_OBJECT_POST_TYPENAME), exporter->getPage(), exporter->getMode())); renderPost(postExporter, *i); } } createPager(getSkin(), exporter->getRoot(), total_posts, posts_to_show, offset); }
void sdl_visualize_clusters(point *points, int numpoints, int *cluster_centersx, int *cluster_centersy, int clusters) { SDL_Init(SDL_INIT_VIDEO); SDL_WM_SetCaption("Cluster Visualization", "SDL Test"); screen = SDL_SetVideoMode(WINW, WINH, 0, 0); SDL_Rect rect = {0, 0, WINW, WINH}; SDL_FillRect(screen, &rect, WHITE); draw_points(points, numpoints, cluster_centersx, cluster_centersy, clusters); debug("Entering input loop..."); SDL_Event event; bool exit = false; while (!exit) { if (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: exit = 1; break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_UP: up = true; break; case SDLK_DOWN: down = true; break; case SDLK_RIGHT: right = true; break; case SDLK_LEFT: left = true; break; case SDLK_ESCAPE: case SDLK_q: exit = 1; break; } break; case SDL_KEYUP: switch (event.key.keysym.sym) { case SDLK_UP: up = false; break; case SDLK_DOWN: down = false; break; case SDLK_RIGHT: right = false; break; case SDLK_LEFT: left = false; break; case SDLK_ESCAPE: case SDLK_q: exit = 1; break; } break; } } if(up == true) adjustOffset(UP); if(down == true) adjustOffset(DOWN); if(left == true) adjustOffset(LEFT); if(right == true) adjustOffset(RIGHT); if(up == true || down == true || left == true || right == true) { draw_points(points, numpoints, cluster_centersx, cluster_centersy, clusters); } SDL_UpdateRect(screen, 0, 0, 0, 0); } SDL_Quit(); }
void MachoExport::exportStore(void) { PolyWord *p; #if (SIZEOF_VOIDP == 8) struct mach_header_64 fhdr; struct segment_command_64 sHdr; struct section_64 *sections = new section_64[memTableEntries+1]; size_t sectionSize = sizeof(section_64); #else struct mach_header fhdr; struct segment_command sHdr; struct section *sections = new section[memTableEntries+1]; size_t sectionSize = sizeof(section); #endif struct symtab_command symTab; unsigned i; // Write out initial values for the headers. These are overwritten at the end. // File header memset(&fhdr, 0, sizeof(fhdr)); fhdr.filetype = MH_OBJECT; fhdr.ncmds = 2; // One for the segment and one for the symbol table. fhdr.sizeofcmds = sizeof(sHdr) + sectionSize * (memTableEntries+1) + sizeof(symTab); fhdr.flags = 0; // The machine needs to match the machine we're compiling for // even if this is actually portable code. #if (SIZEOF_VOIDP == 8) fhdr.magic = MH_MAGIC_64; // (0xfeedfacf) 64-bit magic number #else fhdr.magic = MH_MAGIC; // Feed Face (0xfeedface) #endif #if defined(HOSTARCHITECTURE_X86) fhdr.cputype = CPU_TYPE_I386; fhdr.cpusubtype = CPU_SUBTYPE_I386_ALL; #elif defined(HOSTARCHITECTURE_PPC) fhdr.cputype = CPU_TYPE_POWERPC; fhdr.cpusubtype = CPU_SUBTYPE_POWERPC_ALL; #elif defined(HOSTARCHITECTURE_X86_64) fhdr.cputype = CPU_TYPE_X86_64; fhdr.cpusubtype = CPU_SUBTYPE_X86_64_ALL; #else #error "No support for exporting on this architecture" #endif fwrite(&fhdr, sizeof(fhdr), 1, exportFile); // Write it for the moment. // Segment header. memset(&sHdr, 0, sizeof(sHdr)); #if (SIZEOF_VOIDP == 8) sHdr.cmd = LC_SEGMENT_64; #else sHdr.cmd = LC_SEGMENT; #endif sHdr.nsects = memTableEntries+1; // One for each entry plus one for the tables. sHdr.cmdsize = sizeof(sHdr) + sectionSize * sHdr.nsects; // Add up the sections to give the file size sHdr.filesize = 0; for (i = 0; i < memTableEntries; i++) sHdr.filesize += memTable[i].mtLength; // Do we need any alignment? sHdr.filesize += sizeof(exportDescription) + memTableEntries * sizeof(memoryTableEntry); sHdr.vmsize = sHdr.filesize; // Set them the same since we don't have any "common" area. // sHdr.fileOff is set later. sHdr.maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE; sHdr.initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE; sHdr.flags = 0; // Write it initially. fwrite(&sHdr, sizeof(sHdr), 1, exportFile); // Section header for each entry in the table POLYUNSIGNED sectAddr = sizeof(exportDescription)+sizeof(memoryTableEntry)*memTableEntries; for (i = 0; i < memTableEntries; i++) { memset(&(sections[i]), 0, sectionSize); if (memTable[i].mtFlags & MTF_WRITEABLE) { // Mutable areas ASSERT(!(memTable[i].mtFlags & MTF_EXECUTABLE)); // Executable areas can't be writable. sprintf(sections[i].sectname, "__data"); sprintf(sections[i].segname, "__DATA"); sections[i].flags = S_ATTR_LOC_RELOC | S_REGULAR; } else if (memTable[i].mtFlags & MTF_EXECUTABLE) { sprintf(sections[i].sectname, "__text"); sprintf(sections[i].segname, "__TEXT"); sections[i].flags = S_ATTR_LOC_RELOC | S_ATTR_SOME_INSTRUCTIONS | S_REGULAR; } else { sprintf(sections[i].sectname, "__const"); sprintf(sections[i].segname, "__DATA"); sections[i].flags = S_ATTR_LOC_RELOC | S_REGULAR; } sections[i].addr = sectAddr; sections[i].size = memTable[i].mtLength; sectAddr += memTable[i].mtLength; //sections[i].offset is set later //sections[i].reloff is set later //sections[i].nreloc is set later sections[i].align = 3; // 8 byte alignment // theSection.size is set later } // For the tables. memset(&(sections[memTableEntries]), 0, sectionSize); sprintf(sections[memTableEntries].sectname, "__const"); sprintf(sections[memTableEntries].segname, "__DATA"); sections[memTableEntries].addr = 0; sections[memTableEntries].size = sizeof(exportDescription)+sizeof(memoryTableEntry)*memTableEntries; sections[memTableEntries].align = 3; // 8 byte alignment // theSection.size is set later sections[memTableEntries].flags = S_ATTR_LOC_RELOC | S_ATTR_SOME_INSTRUCTIONS | S_REGULAR; // Write them out for the moment. fwrite(sections, sectionSize * (memTableEntries+1), 1, exportFile); // Symbol table header. memset(&symTab, 0, sizeof(symTab)); symTab.cmd = LC_SYMTAB; symTab.cmdsize = sizeof(symTab); //symTab.symoff is set later //symTab.nsyms is set later //symTab.stroff is set later //symTab.strsize is set later fwrite(&symTab, sizeof(symTab), 1, exportFile); // Create the symbol table first before we mess up the addresses by turning them // into relocations. symTab.symoff = ftell(exportFile); // Global symbols: Just one. Mach prefixes symbols with an underscore. writeSymbol("_poly_exports", N_EXT | N_SECT, memTableEntries, 0); // The export table comes first // We create local symbols because they make debugging easier. They may also // mean that we can use the usual Unix profiling tools. writeSymbol("memTable", N_SECT, memTableEntries, sizeof(exportDescription)); // Then the memTable. for (i = 0; i < memTableEntries; i++) { if (i == ioMemEntry) writeSymbol("ioarea", N_SECT, i, 0); else { char buff[50]; sprintf(buff, "area%0d", i); writeSymbol(buff, N_SECT, i, 0); #if (SIZEOF_VOIDP == 8) // See if we can find the names of any functions. // This seems to break on 32-bit Mac OS X. It seems to align // some relocations onto an 8-byte boundary so we just disable it. char *start = (char*)memTable[i].mtAddr; char *end = start + memTable[i].mtLength; for (p = (PolyWord*)start; p < (PolyWord*)end; ) { p++; PolyObject *obj = (PolyObject*)p; POLYUNSIGNED length = obj->Length(); if (length != 0 && obj->IsCodeObject()) { PolyWord *name = obj->ConstPtrForCode(); // Copy as much of the name as will fit and ignore any extra. // Do we need to worry about duplicates? (void)Poly_string_to_C(*name, buff, sizeof(buff)); writeSymbol(buff, N_SECT, i, (char*)p - start); } p += length; } #endif } } symTab.nsyms = symbolCount; // Create and write out the relocations. for (i = 0; i < memTableEntries; i++) { sections[i].reloff = ftell(exportFile); relocationCount = 0; if (i != ioMemEntry) // Don't relocate the IO area { // Create the relocation table and turn all addresses into offsets. char *start = (char*)memTable[i].mtAddr; char *end = start + memTable[i].mtLength; for (p = (PolyWord*)start; p < (PolyWord*)end; ) { p++; PolyObject *obj = (PolyObject*)p; POLYUNSIGNED length = obj->Length(); if (length != 0 && obj->IsCodeObject()) machineDependent->ScanConstantsWithinCode(obj, this); relocateObject(obj); p += length; } } sections[i].nreloc = relocationCount; } // Additional relocations for the descriptors. sections[memTableEntries].reloff = ftell(exportFile); relocationCount = 0; // Address of "memTable" within "exports". We can't use createRelocation because // the position of the relocation is not in either the mutable or the immutable area. createStructsRelocation(memTableEntries, offsetof(exportDescription, memTable)); // Address of "rootFunction" within "exports" unsigned rootAddrArea = findArea(rootFunction); POLYUNSIGNED rootOffset = (char*)rootFunction - (char*)memTable[rootAddrArea].mtAddr; adjustOffset(rootAddrArea, rootOffset); createStructsRelocation(rootAddrArea, offsetof(exportDescription, rootFunction)); // Addresses of the areas within memtable. for (i = 0; i < memTableEntries; i++) { createStructsRelocation(i, sizeof(exportDescription) + i * sizeof(memoryTableEntry) + offsetof(memoryTableEntry, mtAddr)); } sections[memTableEntries].nreloc = relocationCount; // The symbol name table symTab.stroff = ftell(exportFile); fwrite(stringTable.strings, stringTable.stringSize, 1, exportFile); symTab.strsize = stringTable.stringSize; alignFile(4); exportDescription exports; memset(&exports, 0, sizeof(exports)); exports.structLength = sizeof(exportDescription); exports.memTableSize = sizeof(memoryTableEntry); exports.memTableEntries = memTableEntries; exports.ioIndex = 0; // The io entry is the first in the memory table exports.memTable = (memoryTableEntry *)sizeof(exportDescription); // It follows immediately after this. // Set the value to be the offset relative to the base of the area. We have set a relocation // already which will add the base of the area. exports.rootFunction = (void*)rootOffset; exports.timeStamp = time(NULL); exports.ioSpacing = ioSpacing; exports.architecture = machineDependent->MachineArchitecture(); exports.rtsVersion = POLY_version_number; sections[memTableEntries].offset = ftell(exportFile); fwrite(&exports, sizeof(exports), 1, exportFile); POLYUNSIGNED addrOffset = sizeof(exports)+sizeof(memoryTableEntry)*memTableEntries; for (i = 0; i < memTableEntries; i++) { void *save = memTable[i].mtAddr; memTable[i].mtAddr = (void*)addrOffset; // Set this to the relative address. addrOffset += memTable[i].mtLength; fwrite(&memTable[i], sizeof(memoryTableEntry), 1, exportFile); memTable[i].mtAddr = save; } // Now the binary data. for (i = 0; i < memTableEntries; i++) { alignFile(4); sections[i].offset = ftell(exportFile); fwrite(memTable[i].mtAddr, 1, memTable[i].mtLength, exportFile); } // Rewind to rewrite the headers with the actual offsets. rewind(exportFile); fwrite(&fhdr, sizeof(fhdr), 1, exportFile); // File header fwrite(&sHdr, sizeof(sHdr), 1, exportFile); // Segment header fwrite(sections, sectionSize * (memTableEntries+1), 1, exportFile); // Section headers fwrite(&symTab, sizeof(symTab), 1, exportFile); // Symbol table header fclose(exportFile); exportFile = NULL; delete[](sections); }
/* This is called for each constant within the code. Print a relocation entry for the word and return a value that means that the offset is saved in original word. */ void MachoExport::ScanConstant(byte *addr, ScanRelocationKind code) { PolyWord p = GetConstantValue(addr, code); if (IS_INT(p) || p == PolyWord::FromUnsigned(0)) return; void *a = p.AsAddress(); unsigned aArea = findArea(a); // Set the value at the address to the offset relative to the symbol. POLYUNSIGNED offset = (char*)a - (char*)memTable[aArea].mtAddr; adjustOffset(aArea, offset); switch (code) { case PROCESS_RELOC_DIRECT: // 32 bit address of target { struct relocation_info reloc; setRelocationAddress(addr, &reloc.r_address); reloc.r_symbolnum = aArea+1; // Section numbers start at 1 reloc.r_pcrel = 0; #if (defined(HOSTARCHITECTURE_X86_64)) reloc.r_length = 3; // 8 bytes reloc.r_type = X86_64_RELOC_UNSIGNED; #else reloc.r_length = 2; // 4 bytes reloc.r_type = GENERIC_RELOC_VANILLA; #endif reloc.r_extern = 0; // r_symbolnum is a section number. It should be 1 if we make the IO area a common. for (unsigned i = 0; i < sizeof(PolyWord); i++) { addr[i] = (byte)(offset & 0xff); offset >>= 8; } fwrite(&reloc, sizeof(reloc), 1, exportFile); relocationCount++; } break; #if (defined(HOSTARCHITECTURE_X86) || defined(HOSTARCHITECTURE_X86_64)) case PROCESS_RELOC_I386RELATIVE: // 32 bit relative address { unsigned addrArea = findArea(addr); // If it's in the same area we don't need a relocation because the // relative offset will be unchanged. if (addrArea != aArea) { struct relocation_info reloc; setRelocationAddress(addr, &reloc.r_address); reloc.r_symbolnum = aArea+1; // Section numbers start at 1 reloc.r_pcrel = 1; reloc.r_length = 2; // 4 bytes #if (defined(HOSTARCHITECTURE_X86_64)) reloc.r_type = X86_64_RELOC_SIGNED; #else reloc.r_type = GENERIC_RELOC_VANILLA; #endif reloc.r_extern = 0; // r_symbolnum is a section number. fwrite(&reloc, sizeof(reloc), 1, exportFile); relocationCount++; POLYUNSIGNED addrOffset = (char*)addr - (char*)memTable[addrArea].mtAddr; adjustOffset(addrArea, addrOffset); offset -= addrOffset + 4; for (unsigned i = 0; i < 4; i++) { addr[i] = (byte)(offset & 0xff); offset >>= 8; } } } break; #endif default: ASSERT(0); // Wrong type of relocation for this architecture. } }
void Screen::drawGlyph(u32 x, u32 y, u8 fc, u8 bc, u16 code, bool dw) { if (x >= mWidth || y >= mHeight) return; s32 w = (dw ? FW(2) : FW(1)), h = FH(1); if (x + w > mWidth) w = mWidth - x; if (y + h > mHeight) h = mHeight - y; Font::Glyph *glyph = (Font::Glyph *)Font::instance()->getGlyph(code); if (!glyph) { fillRect(x, y, w, h, bc); return; } s32 top = glyph->top; if (top < 0) top = 0; s32 left = glyph->left; if ((s32)x + left < 0) left = -x; s32 width = glyph->width; if (width > w - left) width = w - left; if ((s32)x + left + width > (s32)mWidth) width = mWidth - ((s32)x + left); if (width < 0) width = 0; s32 height = glyph->height; if (height > h - top) height = h - top; if (y + top + height > mHeight) height = mHeight - (y + top); if (height < 0) height = 0; if (top) fillRect(x, y, w, top, bc); if (left > 0) fillRect(x, y + top, left, height, bc); s32 right = width + left; if (w > right) fillRect((s32)x + right, y + top, w - right, height, bc); s32 bot = top + height; if (h > bot) fillRect(x, y + bot, w, h - bot, bc); x += left; y += top; if (x >= mWidth || y >= mHeight || !width || !height) return; u32 nwidth = width, nheight = height; rotateRect(x, y, nwidth, nheight); u8 *pixmap = glyph->pixmap; u32 wdiff = glyph->width - width, hdiff = glyph->height - height; if (wdiff) { if (mRotateType == Rotate180) pixmap += wdiff; else if (mRotateType == Rotate270) pixmap += wdiff * glyph->pitch; } if (hdiff) { if (mRotateType == Rotate90) pixmap += hdiff; else if (mRotateType == Rotate180) pixmap += hdiff * glyph->pitch; } adjustOffset(x, y); for (; nheight--; y++, pixmap += glyph->pitch) { if ((mScrollType == YWrap) && y > mOffsetMax) y -= mOffsetMax + 1; (this->*draw)(x, y, nwidth, fc, bc, pixmap); } }
/* This is called for each constant within the code. Print a relocation entry for the word and return a value that means that the offset is saved in original word. */ void MachoExport::ScanConstant(byte *addr, ScanRelocationKind code) { PolyWord p = GetConstantValue(addr, code); if (IS_INT(p) || p == PolyWord::FromUnsigned(0)) return; void *a = p.AsAddress(); unsigned aArea = findArea(a); // Set the value at the address to the offset relative to the symbol. POLYUNSIGNED offset = (char*)a - (char*)memTable[aArea].mtAddr; adjustOffset(aArea, offset); switch (code) { case PROCESS_RELOC_DIRECT: // 32 bit address of target { struct relocation_info reloc; setRelocationAddress(addr, &reloc.r_address); reloc.r_symbolnum = aArea+1; // Section numbers start at 1 reloc.r_pcrel = 0; #if (defined(HOSTARCHITECTURE_X86_64)) reloc.r_length = 3; // 8 bytes reloc.r_type = X86_64_RELOC_UNSIGNED; #else reloc.r_length = 2; // 4 bytes reloc.r_type = GENERIC_RELOC_VANILLA; #endif reloc.r_extern = 0; // r_symbolnum is a section number. It should be 1 if we make the IO area a common. for (unsigned i = 0; i < sizeof(PolyWord); i++) { addr[i] = (byte)(offset & 0xff); offset >>= 8; } fwrite(&reloc, sizeof(reloc), 1, exportFile); relocationCount++; } break; #if (defined(HOSTARCHITECTURE_X86)) case PROCESS_RELOC_I386RELATIVE: // 32 bit relative address { unsigned addrArea = findArea(addr); // If it's in the same area we don't need a relocation because the // relative offset will be unchanged. if (addrArea != aArea) { struct relocation_info reloc; setRelocationAddress(addr, &reloc.r_address); reloc.r_symbolnum = aArea+1; // Section numbers start at 1 reloc.r_pcrel = 1; reloc.r_length = 2; // 4 bytes reloc.r_type = GENERIC_RELOC_VANILLA; reloc.r_extern = 0; // r_symbolnum is a section number. fwrite(&reloc, sizeof(reloc), 1, exportFile); relocationCount++; POLYUNSIGNED addrOffset = (char*)addr - (char*)memTable[addrArea].mtAddr; adjustOffset(addrArea, addrOffset); offset -= addrOffset + 4; for (unsigned i = 0; i < sizeof(PolyWord); i++) { addr[i] = (byte)(offset & 0xff); offset >>= 8; } } } break; #endif #ifdef HOSTARCHITECTURE_PPC case PROCESS_RELOC_PPCDUAL16SIGNED: // Power PC - two consecutive words case PROCESS_RELOC_PPCDUAL16UNSIGNED: { struct relocation_info reloc; setRelocationAddress(addr, &reloc.r_address); POLYUNSIGNED hi = offset >> 16; // N.B. No adjustment yet. POLYUNSIGNED lo = offset & 0xffff; // We use two consecutive words for our address but Mach-O requires separate // relocations for each. It stores one half of the address in the instruction // itself and the other half is carried in a PPC_RELOC_PAIR relocation entry. // We need four relocations here in total. reloc.r_symbolnum = aArea+1; // Section numbers start at 1 reloc.r_extern = 0; // r_symbolnum is a section number. reloc.r_pcrel = 0; reloc.r_length = 2; // 4 bytes reloc.r_type = code == PROCESS_RELOC_PPCDUAL16SIGNED ? PPC_RELOC_HA16 : PPC_RELOC_HI16; fwrite(&reloc, sizeof(reloc), 1, exportFile); relocationCount++; // Next must be a "pair" containing the low-order part of the address. // The high-order part is stored in the instruction. reloc.r_symbolnum = 0xffffff; // Not sure why reloc.r_type = PPC_RELOC_PAIR; reloc.r_extern = 0; reloc.r_pcrel = 0; reloc.r_address = lo; fwrite(&reloc, sizeof(reloc), 1, exportFile); relocationCount++; // Now the low-order part. setRelocationAddress(addr+sizeof(PolyWord), &reloc.r_address); reloc.r_symbolnum = aArea+1; // Section numbers start at 1 reloc.r_extern = 0; // r_symbolnum is a section number. reloc.r_pcrel = 0; reloc.r_length = 2; // 4 bytes reloc.r_type = PPC_RELOC_LO16; fwrite(&reloc, sizeof(reloc), 1, exportFile); relocationCount++; // Finally a "pair" containing the high-order part of the address to // match the low-order part in the instruction. reloc.r_symbolnum = 0xffffff; // Not sure why reloc.r_type = PPC_RELOC_PAIR; reloc.r_extern = 0; reloc.r_pcrel = 0; reloc.r_address = hi; // Must NOT be adjusted for sign extension. fwrite(&reloc, sizeof(reloc), 1, exportFile); relocationCount++; // Adjust for sign extension and store in the instruction. if ((lo & 0x8000) && (code == PROCESS_RELOC_PPCDUAL16SIGNED)) hi++; POLYUNSIGNED *pt = (POLYUNSIGNED *)addr; // Store the offset into the instructions. pt[0] = (pt[0] & 0xffff0000) | hi; pt[1] = (pt[1] & 0xffff0000) | lo; } break; #endif default: ASSERT(0); // Wrong type of relocation for this architecture. } }