// Process a constant within the code. This is a direct copy of ScanAddress::ScanConstant // with the addition of the locking. void MTGCProcessMarkPointers::ScanConstant(byte *addressOfConstant, ScanRelocationKind code) { // If this code is in the local area there's the possibility that // ScanObjectAddress could return an updated address for a // constant within the code. This could happen if the code is // in the allocation area or if it has been moved into the // mutable/immutable area by the last incomplete partial GC. // Constants can be aligned on any byte offset so another thread // scanning the same code could see an invalid address if it read // the constant while it was being updated. We put a lock round // this just in case. LocalMemSpace *space = gMem.LocalSpaceForAddress(addressOfConstant); if (space != 0) space->spaceLock.Lock(); PolyWord p = GetConstantValue(addressOfConstant, code); if (space != 0) space->spaceLock.Unlock(); if (! IS_INT(p)) { PolyWord oldValue = p; ScanAddress::ScanAddressAt(&p); if (p != oldValue) // Update it if it has changed. { if (space != 0) space->spaceLock.Lock(); SetConstantValue(addressOfConstant, p, code); if (space != 0) space->spaceLock.Unlock(); } } }
string UserConstExpression::ToString() const { auto Op = GetOp(); if (Op->IsAnon()) { return Op->GetConstantValue()->ToString(); } else { return Op->GetName(); } }
/* 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 PExport::ScanConstant(byte *addr, ScanRelocationKind code) { PolyWord p = GetConstantValue(addr, code); // We put in all the values including tagged constants. PolyObject *obj = ObjCodePtrToPtr(addr); // Put in the byte offset and the relocation type code. fprintf(exportFile, "%" POLYUFMT ",%d,", (POLYUNSIGNED)(addr - (byte*)obj), code); printValue(p); // The value to plug in. fprintf(exportFile, " "); }
// The default action is to call the DEFAULT ScanAddressAt NOT the virtual which means that it calls // ScanObjectAddress for the base address of the object referred to. void ScanAddress::ScanConstant(byte *addressOfConstant, ScanRelocationKind code) { PolyWord p = GetConstantValue(addressOfConstant, code); if (! IS_INT(p)) { PolyWord oldValue = p; ScanAddress::ScanAddressAt(&p); if (p != oldValue) // Update it if it has changed. SetConstantValue(addressOfConstant, p, code); } }
// How a button saves itself to a file int MyButton::SaveLayout(FILE *fp) { switch ( GetButtonType() ) { case FL_OP_INPUT_BUTTON: fprintf(fp, " in \"%s\"\n", label()); break; case FL_OP_OUTPUT_BUTTON: fprintf(fp, " out \"%s\"\n", label()); break; } if ( GetConstantValue() != "" ) { std::string dt; fprintf(fp, " {\n"); fprintf(fp, " dtype %s\n", GetDataTypeStr().c_str()); fprintf(fp, " const %s\n", GetConstantValue().c_str()); fprintf(fp, " }\n"); } else { fprintf(fp, " {\n"); fprintf(fp, " dtype %s\n", GetDataTypeStr().c_str()); fprintf(fp, " }\n"); } return(0); }
/* 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 SaveStateExport::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); // We don't need a relocation if this is relative to the current segment // since the relative address will already be right. if (code == PROCESS_RELOC_I386RELATIVE && aArea == findArea(addr)) return; // Set the value at the address to the offset relative to the symbol. RelocationEntry reloc; setRelocationAddress(addr, &reloc.relocAddress); reloc.targetAddress = (char*)a - (char*)memTable[aArea].mtAddr; reloc.targetSegment = (unsigned)memTable[aArea].mtIndex; reloc.relKind = code; fwrite(&reloc, sizeof(reloc), 1, exportFile); relocationCount++; }
/* 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. } }
/* 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. } }