Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/***************************************************************************
* Copyright (c) 2014 Zephyr Software LLC. All rights reserved.
*
* This software is furnished under a license and/or other restrictive
* terms and may be used and copied only in accordance with such terms
* and the inclusion of the above copyright notice. This software or
* any other copies thereof may not be provided or otherwise made
* available to any other person without the express written consent
* of an authorized representative of Zephyr Software LCC. Title to,
* ownership of, and all rights in the software is retained by
* Zephyr Software LCC.
*
* Zephyr Software LLC. Proprietary Information
*
* Unless otherwise specified, the information contained in this
* directory, following this legend, and/or referenced herein is
* Zephyr Software LLC. (Zephyr) Proprietary Information.
*
* CONTACT
*
* For technical assistance, contact Zephyr Software LCC. at:
*
*
* Zephyr Software, LLC
* 2040 Tremont Rd
* Charlottesville, VA 22911
*
* E-mail: jwd@zephyr-software.com
**************************************************************************/
#include <zipr_sdk.h>
#include <string>
#include <algorithm>
#include "utils.hpp"
#include "Rewrite_Utility.hpp"
#include "unpin.h"
#include <memory>
#include <inttypes.h>
using namespace libIRDB;
using namespace std;
using namespace Zipr_SDK;
using namespace ELFIO;
static bool arg_has_memory(const ARGTYPE &arg)
{
if(arg.ArgType&MEMORY_TYPE)
return true;
return false;
}
static std::string findAndReplace(const std::string& in_str, const std::string& oldStr, const std::string& newStr)
{
std::string str=in_str;
size_t pos = 0;
while((pos = str.find(oldStr, pos)) != std::string::npos)
{
str.replace(pos, oldStr.length(), newStr);
pos += newStr.length();
}
return str;
}
static bool has_cfi_reloc(Instruction_t* insn)
{
for(
RelocationSet_t::iterator rit2=insn->GetRelocations().begin();
rit2!=insn->GetRelocations().end();
rit2++
)
{
/* check for a nonce relocation */
if ( (*rit2) -> GetType().find("cfi_nonce") != string::npos )
{
return true;
}
}
return false;
}
bool Unpin_t::should_cfi_pin(Instruction_t* insn)
{
// add command line option that:
// 1) return false if !has_cfi_reloc(insn)
// 2) return true if option is on.
ZiprOptionsNamespace_t *Unpin_t::RegisterOptions(ZiprOptionsNamespace_t *global)
ZiprOptionsNamespace_t *unpin_ns = new ZiprOptionsNamespace_t("unpin");
m_should_cfi_pin.SetDescription("Pin CFI instructions.");
unpin_ns->AddOption(&m_should_cfi_pin);
m_on.SetDescription("Turn unpin plugin on/off.");
unpin_ns->AddOption(&m_on);
m_max_unpins.SetDescription("Set how many unpins are allowed, useful for debugging.");
unpin_ns->AddOption(&m_max_unpins);
{
DoUnpinForScoops();
DoUnpinForFixedCalls();
}
// scan instructions and process instruction relocs that can be unpinned.
void Unpin_t::DoUnpinForFixedCalls()
{
if(m_max_unpins != -1 && unpins>=m_max_unpins)
return;
auto insn_unpins=0;
auto missed_unpins=0;
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
for(
InstructionSet_t::iterator it=zo->GetFileIR()->GetInstructions().begin();
it!=zo->GetFileIR()->GetInstructions().end();
++it
)
{
Instruction_t* from_insn=*it;
for(
RelocationSet_t::iterator rit=from_insn->GetRelocations().begin();
rit!=from_insn->GetRelocations().end();
rit++
)
{
Relocation_t* reloc=*rit;
// this probably won't work on shared objects.
// complicated with the push64-reloc plugin also rewriting these things?
if(reloc->GetType()==string("32-bit") || reloc->GetType()==string("push64"))
{
// skip if there's no WRT, that means it's unpinned for something besides a fixed call.
if(reloc->GetWRT()==NULL)
continue;
// getWRT returns an BaseObj, but this reloc type expects an instruction
// safe cast and check.
Instruction_t* wrt_insn=dynamic_cast<Instruction_t*>(reloc->GetWRT());
assert(wrt_insn);
if(should_cfi_pin(wrt_insn))
continue;
// leave this for debugging I guess?
if(wrt_insn->GetIndirectBranchTargetAddress() && wrt_insn->GetIndirectBranchTargetAddress()->GetVirtualOffset()!=0)
{
cout<<"Unpin::Found "<<reloc->GetType()<<" relocation for pinned insn at "<<hex<<
wrt_insn->GetIndirectBranchTargetAddress()->GetVirtualOffset()<<endl;
}
else
{
cout<<"Unpin::Warn: unpin found non-IBTA to unpin. probably it's unpinned twice. continuing anyhow."<<endl;
}
PlacementQueue_t* pq=zo->GetPlacementQueue();
assert(pq);
// create a new dollop for the unpinned IBT
// and add it to the placement queue.
Dollop_t *newDoll=zo->GetDollopManager()->AddNewDollops(wrt_insn);
pq->insert(std::pair<Dollop_t*,RangeAddress_t>(newDoll, 0));
unpins++;
insn_unpins++;
if(m_max_unpins != -1 && unpins>=m_max_unpins)
return;
cout<<"# ATTRIBUTE Zipr_Unpinning::insn_unpin_total_unpins="<<dec<<insn_unpins<<endl;
cout<<"# ATTRIBUTE Zipr_Unpinning::insn_unpin_missed_unpins="<<dec<<missed_unpins<<endl;
}
void Unpin_t::DoUnpinForScoops()
if(m_max_unpins != -1 && unpins>=m_max_unpins)
return;
auto missed_unpins=0;
auto scoop_unpins=0;
for(
DataScoopSet_t::iterator it=zo->GetFileIR()->GetDataScoops().begin();
it!=zo->GetFileIR()->GetDataScoops().end();
++it
)
{
DataScoop_t* scoop=*it;
for(
RelocationSet_t::iterator rit=scoop->GetRelocations().begin();
rit!=scoop->GetRelocations().end();
rit++
)
{
Relocation_t* reloc=*rit;
if(reloc->GetType()==string("data_to_insn_ptr"))
{
Instruction_t* insn=dynamic_cast<Instruction_t*>(reloc->GetWRT());
// getWRT returns an BaseObj, but this reloc type expects an instruction
// safe cast and check.
assert(insn);
// leave this for debugging I guess?
if(insn->GetIndirectBranchTargetAddress() && insn->GetIndirectBranchTargetAddress()->GetVirtualOffset()!=0)
{
cout<<"Unpin::Found data_to_insn_ptr relocation for pinned insn:"
<<hex<<insn->GetBaseID()<<":" <<insn->getDisassembly()<<" at "
<<hex<< insn->GetIndirectBranchTargetAddress()->GetVirtualOffset()<<endl;
cout<<"Unpin::Warn: unpin found non-IBTA to unpin for insn:"
<<hex<<insn->GetBaseID()<<":" <<insn->getDisassembly()
<<". probably it's unpinned twice. continuing anyhow."<<endl;
bool found=should_cfi_pin(insn);
/* don't unpin if we found one */
if(found)
{
cout<<"Unpin::Not unpinning because CFI is requesting a nonce."<<endl;
{
PlacementQueue_t* pq=zo->GetPlacementQueue();
assert(pq);
// create a new dollop for the unpinned IBT
// and add it to the placement queue.
Dollop_t *newDoll=zo->GetDollopManager()->AddNewDollops(insn);
pq->insert(std::pair<Dollop_t*,RangeAddress_t>(newDoll, 0));
unpins++;
scoop_unpins++;
if(m_max_unpins != -1 && unpins>=m_max_unpins)
return;
cout<<"# ATTRIBUTE Zipr_Unpinning::scoop_unpin_total_unpins="<<dec<<scoop_unpins<<endl;
cout<<"# ATTRIBUTE Zipr_Unpinning::scoop_unpin_missed_unpins="<<dec<<missed_unpins<<endl;
Zipr_SDK::ZiprPreference Unpin_t::RetargetCallback(
const RangeAddress_t &callback_address,
const DollopEntry_t *callback_entry,
RangeAddress_t &target_address)
{
if(!m_on) return Zipr_SDK::ZiprPluginInterface_t::RetargetCallback(callback_address, callback_entry, target_address);
unpins++;// unpinning a call to a scoop.
if(m_max_unpins != -1 && unpins>=m_max_unpins)
return Zipr_SDK::ZiprPluginInterface_t::RetargetCallback(callback_address, callback_entry, target_address);
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
MemorySpace_t &ms=*zo->GetMemorySpace();
Instruction_t *insn = callback_entry->Instruction();
Zipr_SDK::InstructionLocationMap_t &locMap=*(zo->GetLocationMap());
for(
RelocationSet_t::iterator rit=insn->GetRelocations().begin();
rit!=insn->GetRelocations().end();
rit++
)
{
Relocation_t *reloc = *rit;
if (reloc->GetType()==string("callback_to_scoop"))
{
DataScoop_t *wrt = dynamic_cast<DataScoop_t*>(reloc->GetWRT());
int addend = reloc->GetAddend();
target_address = wrt->GetStart()->GetVirtualOffset() + addend;
if (m_verbose) {
cout << "Unpin::callback_to_scoop: target_addr "
<< std::hex << target_address << endl;
}
}
}
return Must;
}
void Unpin_t::DoUpdate()
{
DoUpdateForScoops();
DoUpdateForInstructions();
}
// scan for instructions that were placed, and now need an update.
void Unpin_t::DoUpdateForInstructions()
{
int unpins=0;
int missed_unpins=0;
MemorySpace_t &ms=*zo->GetMemorySpace();
Zipr_SDK::InstructionLocationMap_t &locMap=*(zo->GetLocationMap());
for(
InstructionSet_t::iterator it=zo->GetFileIR()->GetInstructions().begin();
it!=zo->GetFileIR()->GetInstructions().end();
++it
)
{
Instruction_t* from_insn=*it;
//DISASM disasm;
//Disassemble(from_insn,disasm);
// const auto disasm=DecodedInstruction_t(from_insn);
// const auto operands=disasm.getOperands();
ARGTYPE* the_arg=NULL;
if(arg_has_memory(disasm.Argument1))
the_arg=&disasm.Argument1;
if(arg_has_memory(disasm.Argument2))
the_arg=&disasm.Argument2;
if(arg_has_memory(disasm.Argument3))
the_arg=&disasm.Argument3;
if(arg_has_memory(disasm.Argument4))
the_arg=&disasm.Argument4;
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
for(
RelocationSet_t::iterator rit=from_insn->GetRelocations().begin();
rit!=from_insn->GetRelocations().end();
rit++
)
{
Relocation_t* reloc=*rit;
// this probably won't work on shared objects.
// complicated with the push64-reloc plugin also rewriting these things?
if(reloc->GetType()==string("32-bit") || reloc->GetType()==string("push64"))
{
// skip if there's no WRT, that means it's unpinned for something besides a fixed call.
if(reloc->GetWRT()==NULL)
continue;
// getWRT returns an BaseObj, but this reloc type expects an instruction
// safe cast and check.
Instruction_t* wrt_insn=dynamic_cast<Instruction_t*>(reloc->GetWRT());
assert(wrt_insn);
if(should_cfi_pin(wrt_insn))
continue;
libIRDB::virtual_offset_t wrt_insn_location=locMap[wrt_insn];
libIRDB::virtual_offset_t from_insn_location=locMap[from_insn];
// 32-bit code and main executables just push a full 32-bit addr.
{
// not handled in push64_relocs which is disabled for shared objects.
// expecting a 32-bit push, length=5
assert(from_insn->GetDataBits()[0]==0x68);
assert(from_insn->GetDataBits().size()==5);
// down and upcast to ensure we fit in 31-bits.
assert(wrt_insn_location == (libIRDB::virtual_offset_t)(int)wrt_insn_location);
assert(sizeof(int)==4); // paranoid.
unsigned char newpush[5];
newpush[0]=0x68;
*(int*)&newpush[1]=(int)wrt_insn_location;
cout<<"Unpin::Updating push32/push64-exe insn:"
<<dec<<from_insn->GetBaseID()<<":"<<from_insn->getDisassembly()<<"@"<<hex<<from_insn_location<<" to point at "
<<dec<<wrt_insn ->GetBaseID()<<":"<<wrt_insn ->getDisassembly()<<"@"<<hex<<wrt_insn_location <<endl;
for(unsigned int i=0;i<from_insn->GetDataBits().size();i++)
{
unsigned char newbyte=newpush[i];
ms[from_insn_location+i]=newbyte;
}
jdh8d
committed
}
// shared object
// gets a call/sub [$rsp], const pair.
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
{
// handled in push64_relocs which is required for shared objects.
#if 0
auto call_insn=from_insn;
auto sub_insn=call_insn->GetTarget();
libIRDB::virtual_offset_t sub_insn_location=locMap[sub_insn];
assert(sub_insn);
auto subbits=sub_insn->GetDataBits();
// must be sub [$rsp], const
assert( subbits[0]==(char)0x48 && subbits[1]==(char)0x81 &&
subbits[2]==(char)0x2c && subbits[3]==(char)0x24);
unsigned char newoffset[sizeof(int)]={};
// grab old offset from memory space
for(unsigned int i=0;i<from_insn->GetDataBits().size();i++)
newoffset[i]=ms[sub_insn_location+4+i];
// update it.
*(unsigned int*)newoffset += wrt_insn_location;
// write memory space.
for(unsigned int i=0;i<sizeof(int); i++)
ms[sub_insn_location+4+i]=newoffset[i];
cout<<"Unpin::Updating push64-so insn:"
<<dec<<from_insn->GetBaseID()<<"@"<<hex<<from_insn_location<<" to point at "
<<dec<<wrt_insn ->GetBaseID()<<"@"<<hex<<wrt_insn_location <<endl;
jdh8d
committed
}
// instruction has a pcrel memory operand.
else if(reloc->GetType()==string("pcrel") && reloc->GetWRT()!=NULL)
{
const auto disasm=DecodedInstruction_t(from_insn);
const auto operands=disasm.getOperands();
const auto the_arg_it=find_if(ALLOF(operands),[](const DecodedOperand_t& op){ return op.isMemory() && op.isPcrel(); });
BaseObj_t* bo_wrt=reloc->GetWRT();
DataScoop_t* scoop_wrt=dynamic_cast<DataScoop_t*>(reloc->GetWRT());
Instruction_t* insn_wrt=dynamic_cast<Instruction_t*>(reloc->GetWRT());
assert(the_arg_it!=operands.end());
const auto the_arg=*the_arg_it;
virtual_offset_t rel_addr1=the_arg.getMemoryDisplacement(); // ->Memory.Displacement;
rel_addr1+=from_insn->GetDataBits().size();
// const auto disasm=DecodedInstruction_t(from_insn);
// const auto operands=disasm.getOperands();
jdh8d
committed
int disp_offset=disasm.getMemoryDisplacementOffset(the_arg,from_insn); // the_arg->Memory.DisplacementAddr-disasm.EIP;
int disp_size=the_arg.getMemoryDisplacementEncodingSize(); // the_arg->Memory.DisplacementSize;
libIRDB::virtual_offset_t from_insn_location=locMap[from_insn];
assert(disp_size==4);
assert(0<disp_offset && disp_offset<=from_insn->GetDataBits().size() - disp_size);
libIRDB::virtual_offset_t to_addr=0xdeadbeef; // noteable value that shouldn't be used.
string convert_string;
assert(bo_wrt);
if(scoop_wrt)
{
to_addr=scoop_wrt->GetStart()->GetVirtualOffset();
convert_string=string("scoop ")+scoop_wrt->GetName();
}
else if(insn_wrt)
{
to_addr=locMap[insn_wrt];
convert_string=string("insn ")+to_string(insn_wrt->GetBaseID())+
":"+insn_wrt->getDisassembly();
}
else assert(0);
int new_disp=rel_addr1 + to_addr - from_insn->GetDataBits().size()-from_insn_location;
from_insn->SetDataBits(from_insn->GetDataBits().replace(disp_offset,
disp_size, (char*)&new_disp, disp_size));
// update the instruction in the memory space.
for(unsigned int i=0;i<from_insn->GetDataBits().size();i++)
{
unsigned char newbyte=from_insn->GetDataBits()[i];
ms[from_insn_location+i]=newbyte;
}
//DISASM disasm2;
//Disassemble(from_insn,disasm2);
const auto disasm2=DecodedInstruction_t(from_insn);
cout<<"unpin:pcrel:new_disp="<<hex<<new_disp<<endl;
cout<<"unpin:pcrel:new_insn_addr="<<hex<<from_insn_location<<endl;
cout<<"unpin:pcrel:Converting "<<hex<<from_insn->GetBaseID()<<":"<<disasm.getDisassembly() /*CompleteInstr*/
<<" to "<<disasm2.getDisassembly() /*CompleteInstr*/<<" wrt "<< convert_string <<endl;
}
// instruction has a absolute memory operand that needs it's displacement updated.
else if(reloc->GetType()==string("absoluteptr_to_scoop"))
{
const auto disasm=DecodedInstruction_t(from_insn);
const auto operands=disasm.getOperands();
// push/pop from memory might have a memory operand with no string to represent the implicit stack operand.
const auto the_arg_it=find_if(ALLOF(operands),[](const DecodedOperand_t& op){ return op.isMemory() && op.getString()!=""; });
DataScoop_t* wrt=dynamic_cast<DataScoop_t*>(reloc->GetWRT());
assert(wrt);
const auto &the_arg=*the_arg_it;
virtual_offset_t rel_addr1=the_arg.getMemoryDisplacement(); // ->Memory.Displacement;
//virtual_offset_t rel_addr1=the_arg->Memory.Displacement;
jdh8d
committed
int disp_offset=disasm.getMemoryDisplacementOffset(the_arg,from_insn); // the_arg->Memory.DisplacementAddr-disasm.EIP;
int disp_size=the_arg.getMemoryDisplacementEncodingSize(); // the_arg->Memory.DisplacementSize;
//int disp_offset=the_arg->Memory.DisplacementAddr-disasm.EIP;
//int disp_size=the_arg->Memory.DisplacementSize;
assert(disp_size==4);
assert(0<disp_offset && disp_offset<=from_insn->GetDataBits().size() - disp_size);
assert(reloc->GetWRT());
unsigned int new_disp=the_arg.getMemoryDisplacement()/*the_arg->Memory.Displacement */+ wrt->GetStart()->GetVirtualOffset();
from_insn->SetDataBits(from_insn->GetDataBits().replace(disp_offset, disp_size, (char*)&new_disp, disp_size));
// update the instruction in the memory space.
libIRDB::virtual_offset_t from_insn_location=locMap[from_insn];
for(unsigned int i=0;i<from_insn->GetDataBits().size();i++)
{
unsigned char newbyte=from_insn->GetDataBits()[i];
ms[from_insn_location+i]=newbyte;
//cout<<"Updating push["<<i<<"] from "<<hex<<oldbyte<<" to "<<newbyte<<endl;
}
//DISASM disasm2;
//Disassemble(from_insn,disasm2);
const auto disasm2=DecodedInstruction_t(from_insn);
cout<<"unpin:absptr_to_scoop:Converting "<<hex<<from_insn->GetBaseID()<<":"<<disasm.getDisassembly()/*CompleteInstr*/
<<" to "<<disasm2.getDisassembly()/*CompleteInstr*/<<" for scoop: "<<wrt->GetName()<<endl;
}
// instruction has an immediate that needs an update.
else if(reloc->GetType()==string("immedptr_to_scoop"))
{
DataScoop_t* wrt=dynamic_cast<DataScoop_t*>(reloc->GetWRT());
assert(wrt);
const auto disasm=DecodedInstruction_t(from_insn);
virtual_offset_t rel_addr2=disasm.getImmediate(); // disasm.Instruction.Immediat;
virtual_offset_t new_addr = rel_addr2 + wrt->GetStart()->GetVirtualOffset();
from_insn->SetDataBits(from_insn->GetDataBits().replace(from_insn->GetDataBits().size()-4, 4, (char*)&new_addr, 4));
libIRDB::virtual_offset_t from_insn_location=locMap[from_insn];
for(unsigned int i=0;i<from_insn->GetDataBits().size();i++)
{
unsigned char newbyte=from_insn->GetDataBits()[i];
ms[from_insn_location+i]=newbyte;
//cout<<"Updating push["<<i<<"] from "<<hex<<oldbyte<<" to "<<newbyte<<endl;
}
//DISASM disasm2;
//Disassemble(from_insn,disasm2);
const auto disasm2=DecodedInstruction_t(from_insn);
cout<<"unpin:immedptr_to_scoop:Converting "<<hex<<from_insn->GetBaseID()<<":"<<disasm.getDisassembly() /*CompleteInstr*/
<<" to "<<disasm2.getDisassembly() /*CompleteInstr*/<<" for scoop: "<<wrt->GetName()<<endl;
else if(reloc->GetType()==string("callback_to_scoop"))
{
DataScoop_t *wrt = dynamic_cast<DataScoop_t*>(reloc->GetWRT());
char bytes[]={(char)0x48,
(char)0x8d,
(char)0x64,
(char)0x24,
(char)(64/0x08)}; // lea rsp, [rsp+8]
uintptr_t call_addr = 0x0, at = 0x0;
uint32_t target_addr = 0x0;
if (m_verbose)
cout << "The call insn is "
<< from_insn->GetDataBits().length() << " bytes long." << endl;
call_addr = locMap[from_insn];
if (m_verbose) {
cout << "Unpin::callback_to_scoop: call_addr "
<< std::hex << call_addr << endl;
}
*/
at = call_addr + 1;
at = call_addr + from_insn->GetDataBits().length();
ms.PlopBytes(at, bytes, sizeof(bytes));
/*
* Turn off the following flags so that this
* is left alone when it is being plopped.
*/
from_insn->SetTarget(NULL);
from_insn->SetCallback("");
}
}
}
}
void Unpin_t::DoUpdateForScoops()
unsigned int byte_width=zo->GetFileIR()->GetArchitectureBitWidth()/8;
for(
DataScoopSet_t::iterator it=zo->GetFileIR()->GetDataScoops().begin();
it!=zo->GetFileIR()->GetDataScoops().end();
++it
)
{
DataScoop_t* scoop=*it;
assert(scoop->GetEnd()->GetVirtualOffset() - scoop->GetStart()->GetVirtualOffset()+1 == scoop->GetSize());
assert(scoop->GetContents().size() == scoop->GetSize());
string scoop_contents=scoop->GetContents();
for(
RelocationSet_t::iterator rit=scoop->GetRelocations().begin();
rit!=scoop->GetRelocations().end();
rit++
)
{
Relocation_t* reloc=*rit;
if(reloc->GetType()==string("data_to_insn_ptr"))
{
virtual_offset_t reloff=reloc->GetOffset();
Instruction_t* insn=dynamic_cast<Instruction_t*>(reloc->GetWRT());
// getWRT returns an BaseObj, but this reloc type expects an instruction
// safe cast and check.
assert(insn);
Zipr_SDK::InstructionLocationMap_t &locMap=*(zo->GetLocationMap());
libIRDB::virtual_offset_t newLoc=locMap[insn];
cout<<"Unpin::Unpinned data_to_insn_ptr insn ("<<hex<<insn->GetBaseID()<<":"
<<insn->getDisassembly()<<") with offset="<<hex<<reloc->GetOffset()
<<". Insn moved to "<<hex<<newLoc<<endl;
bool found=should_cfi_pin(insn);
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
/* don't unpin if we found one */
if(found)
{
cout<<"Unpin::Skipping update because CFI is requesting a nonce."<<endl;
}
else
{
// determine how big the ptr is.
int ptrsize=zo->GetFileIR()->GetArchitectureBitWidth()/8;
char addr[ptrsize];
// convert it to bytes.
switch(ptrsize)
{
case 4:
*(int*)addr=newLoc;
break;
case 8:
*(long long*)addr=newLoc;
break;
default:
assert(0);
}
// copy in new ptr.
for(int i=0;i<ptrsize;i++)
scoop_contents[reloff+i]=addr[i];
}
}
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
else if(reloc->GetType()==string("dataptr_to_scoop"))
{
DataScoop_t *wrt=dynamic_cast<DataScoop_t*>(reloc->GetWRT());
assert(wrt);
virtual_offset_t val_to_patch=0;
const char* data=scoop_contents.c_str();
if(byte_width==4)
val_to_patch=*(int*)&data[reloc->GetOffset()];
else if(byte_width==8)
val_to_patch=*(long long*)&data[reloc->GetOffset()];
else
assert(0);
// wrt scoop should be placed.
assert(wrt->GetStart()->GetVirtualOffset() !=0 );
virtual_offset_t new_val_to_patch=val_to_patch + wrt->GetStart()->GetVirtualOffset();
if(byte_width==4)
{
unsigned int intnewval=(unsigned int)new_val_to_patch; // 64->32 narrowing OK.
scoop_contents.replace(reloc->GetOffset(), byte_width, (char*)&intnewval, byte_width);
}
else if(byte_width==8)
{
scoop_contents.replace(reloc->GetOffset(), byte_width, (char*)&new_val_to_patch, byte_width);
}
else
assert(0);
cout<<"Patched "<<scoop->GetName()<<"+"<<hex<<reloc->GetOffset()<<" to value "<<hex<<new_val_to_patch<<endl;
}