You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
583 lines
23 KiB
583 lines
23 KiB
"""
|
|
This plugin extension allows a project file to easily build Pin tools.
|
|
To use this extension, a project file can define the following elements:
|
|
|
|
PINHOME = '...'
|
|
PINTOOLS = [...]
|
|
PINLIBRARIES = [...]
|
|
|
|
The following variables are also available to the project file:
|
|
|
|
$PIN Expands to the pathname to Pin, the program you should
|
|
run to launch Pin. It is either absolute, or relative
|
|
to the project file, depending on PINHOME.
|
|
$PINTOOL(os,x) Expands to the name of a Pin tool whose root name is "x",
|
|
using the naming conventions on the OS whose name is "os".
|
|
$PINTOOL(x) Equivalent to $PINTOOL($HOSTOS,x).
|
|
$PINHOME_TYPE Expands to either "kit" or "source", depending on whether
|
|
PINHOME points to a Pin kit or source tree.
|
|
|
|
PINHOME should be set to the pathname of a Pin distribution kit. If you are
|
|
a Pin developer, you may also set PINHOME to the root of the Pin source tree.
|
|
The pathname can either be absolute or relative to the project file.
|
|
|
|
PINTOOLS defines the list of Pin tools to build. Format looks like this:
|
|
|
|
PINTOOLS = [
|
|
{'name': 'mytool',
|
|
'files': [
|
|
{'file': 'mytool.cpp'},
|
|
{'file': 'foo.cpp'},
|
|
],
|
|
},
|
|
{'name': 'myothertool',
|
|
'files': [
|
|
{'file': 'other.cpp'},
|
|
],
|
|
},
|
|
]
|
|
|
|
PINLIBRARIES can optionally be used to build a library that will later
|
|
be linked into a Pin tool. Its format is similar to LIBRARIES, but you
|
|
cannot use the 'libtypes' key.
|
|
|
|
PINLIBRARIES = [
|
|
{'name': 'mylib',
|
|
'files': [
|
|
{'file': 'mylib1.cpp'},
|
|
{'file': 'mylib2.cpp'},
|
|
],
|
|
},
|
|
]
|
|
|
|
This extension reads the PINTOOLS and PINLIBRARIES sections after the
|
|
project's PRECOMMANDS section is executed, so PRECOMMANDS can legally
|
|
add content to PINTOOLS and PINLIBRARIES. The variable values are set
|
|
before PRECOMMANDS, so they are available to these commands. The value
|
|
of PINHOME must be set prior to PRECOMMANDS and may not change afterwards.
|
|
"""
|
|
|
|
|
|
import os
|
|
import tsconsapi
|
|
import sel
|
|
|
|
|
|
# Maps a 'proj' handle to a 2-tuple (pinhome, pintype). Where
|
|
# 'pinhome' is the value of PINHOME, captured in APPLY_EARLY, and
|
|
# 'pintype' is the type of that Pin tree.
|
|
#
|
|
PinToolDefs = {}
|
|
|
|
|
|
def APPLY_EARLY(proj, namespace):
|
|
"""
|
|
Execute the "early" phase for this plugin extension. The early
|
|
phase happens before the project's PRECOMMANDS are executed.
|
|
|
|
@param proj: Handle to a TSCons project.
|
|
@type proj: Unspecified handle type.
|
|
@param namespace: Namespace of the project file
|
|
@type namespace: Handle returned from 'import'.
|
|
"""
|
|
|
|
# Issue an error if we don't know how to build Pin tools for this target.
|
|
#
|
|
if 'PINTOOLS' in namespace or 'PINLIBRARIES' in namespace:
|
|
if not ExtensionSupportsTarget(proj):
|
|
tsconsapi.Abort("Project '" + tsconsapi.ProjName(proj) + "' uses TSCons 'pintool' extension, "
|
|
"but that extension is not supported for this target.")
|
|
|
|
# If there is a PINHOME, figure out the type (kit vs. source tree). Create
|
|
# project variables in the "early" phase, so they are available to the
|
|
# project's PRECOMMANDS.
|
|
#
|
|
pinHome = namespace.get('PINHOME')
|
|
pinType = None
|
|
if pinHome:
|
|
pinHome = tsconsapi.SubstituteVariables(proj, pinHome)
|
|
pinType = IdentifyPinType(proj, pinHome)
|
|
if not pinType:
|
|
tsconsapi.Abort("Project '" + tsconsapi.ProjName(proj) +
|
|
"', PINHOME does not look like a Pin source or kit tree.")
|
|
tsconsapi.AddProjVarSimple(proj, 'PINHOME_TYPE', pinType)
|
|
tsconsapi.AddProjVarSimple(proj, 'PIN', GetPinPath(proj, pinHome, pinType))
|
|
|
|
# All projects get a definition of $PINTOOL(x).
|
|
#
|
|
tsconsapi.AddProjVarFunc(proj, 'PINTOOL', CalculatePintoolVar)
|
|
|
|
# Save the value of PINHOME, so we can get it later in APPLY_LATE().
|
|
#
|
|
global PinToolDefs
|
|
PinToolDefs[proj] = (pinHome, pinType)
|
|
|
|
|
|
def APPLY_LATE(proj, namespace):
|
|
"""
|
|
Execute the "late" phase for this plugin extension. The late
|
|
phase happens after the project's PRECOMMANDS are executed.
|
|
|
|
@param proj: Handle to a TSCons project.
|
|
@type proj: Unspecified handle type.
|
|
@param namespace: Namespace of the project file
|
|
@type namespace: Handle returned from 'import'.
|
|
"""
|
|
|
|
# Get the value of PINHOME that we captured in APPLY_EARLY. Make sure it hasn't
|
|
# changed.
|
|
#
|
|
(pinHome, pinType) = PinToolDefs[proj]
|
|
pinHomeLate = namespace.get('PINHOME')
|
|
if pinHomeLate:
|
|
pinHomeLate = tsconsapi.SubstituteVariables(proj, pinHomeLate)
|
|
if pinHome != pinHomeLate:
|
|
tsconsapi.Abort("Project '" + tsconsapi.ProjName(proj) +
|
|
"', Value of PINHOME changed during PRECOMMANDS from '" +
|
|
pinHome + "' to '" + pinHomeLate + "'.")
|
|
|
|
# Create build rules from the PINTOOLS and PINLIBRARIES sections. We
|
|
# do this in the "late" phase so that PRECOMMANDS can add dynamic content
|
|
# to these sections.
|
|
#
|
|
if 'PINTOOLS' in namespace:
|
|
ApplyPintools(proj, namespace, pinHome, pinType)
|
|
if 'PINLIBRARIES' in namespace:
|
|
ApplyPinlibraries(proj, namespace)
|
|
|
|
|
|
|
|
# ------------- Private -------------
|
|
|
|
def ExtensionSupportsTarget(proj):
|
|
"""
|
|
Determine if we know how to build Pin tools for the current target.
|
|
|
|
@param proj: Handle to a TSCons project.
|
|
@type proj: Unspecified handle type.
|
|
|
|
@return: TRUE if building Pin tools is supported.
|
|
@rtype: Boolean.
|
|
"""
|
|
|
|
cpu = tsconsapi.SubstituteVariables(proj, '$TARGETCPU')
|
|
os = tsconsapi.SubstituteVariables(proj, '$TARGETOS')
|
|
|
|
# This extension probably does not need to change in order to support BSD on IA32.
|
|
# However, there's no Pin yet for that target, so it's impossible to test.
|
|
#
|
|
if os == 'linux' and cpu in ['ia32', 'intel64']:
|
|
return True
|
|
if os == 'windows' and cpu in ['ia32', 'intel64']:
|
|
return True
|
|
if os == 'bsd' and cpu in ['intel64']:
|
|
return True
|
|
if os == 'mac' and cpu in ['ia32', 'intel64']:
|
|
return True
|
|
return False
|
|
|
|
|
|
def ApplyPintools(proj, namespace, pinHome, pinType):
|
|
"""
|
|
Process the PINTOOLS section of a project.
|
|
|
|
@param proj: Handle to a TSCons project.
|
|
@type proj: Unspecified handle type.
|
|
@param namespace: Namespace of the project file
|
|
@type namespace: Handle returned form 'import'.
|
|
@param pinHome: The value of PINHOME, or the empty string if it isn't defined.
|
|
@type pinHome: String.
|
|
@param pinType: Either "kit" or "source", depending on what PINHOME refers to.
|
|
@type pinType: String.
|
|
"""
|
|
|
|
pintools = namespace.get('PINTOOLS')
|
|
if not pinHome:
|
|
tsconsapi.Abort("Project '" + tsconsapi.ProjName(proj) + "' must specify PINHOME.")
|
|
|
|
includes = namespace.get('INCLUDES')
|
|
if includes == None:
|
|
includes = []
|
|
namespace['INCLUDES'] = includes
|
|
defines = namespace.get('DEFINES')
|
|
if defines == None:
|
|
defines = []
|
|
namespace['DEFINES'] = defines
|
|
libs = namespace.get('LIBRARIES')
|
|
if libs == None:
|
|
libs = []
|
|
namespace['LIBRARIES'] = libs
|
|
|
|
if pinType == 'source':
|
|
ApplyPintoolsToSource(pinHome, pintools, includes, defines, libs)
|
|
elif pinType == 'kit':
|
|
ApplyPintoolsToKit(pinHome, pintools, includes, defines, libs)
|
|
|
|
|
|
def ApplyPinlibraries(proj, namespace):
|
|
"""
|
|
Process the PINLIBRARIES section of a project.
|
|
|
|
@param proj: Handle to a TSCons project.
|
|
@type proj: Unspecified handle type.
|
|
@param namespace: Namespace of the project file
|
|
@type namespace: Handle returned form 'import'.
|
|
"""
|
|
|
|
pinlibs = namespace.get('PINLIBRARIES')
|
|
libs = namespace.get('LIBRARIES')
|
|
if libs == None:
|
|
libs = []
|
|
namespace['LIBRARIES'] = libs
|
|
|
|
for lib in pinlibs:
|
|
if not 'name' in lib:
|
|
tsconsapi.Abort("PINLIBRARIES element must contain 'name'.")
|
|
name = lib['name']
|
|
opts = lib.get('toolchain-options', [])
|
|
files = lib.get('files', None)
|
|
selector = lib.get('selector', None)
|
|
outdir = lib.get('outdir', None)
|
|
noprefix = lib.get('noprefix', None)
|
|
|
|
ApplyCommonOptionsForPinToolsAndLibraries(opts)
|
|
|
|
# We require libraries that are linked into Pin tools to be static for now.
|
|
# On Windows, there are restrictions that prevent tools from using DLL libraries.
|
|
#
|
|
libtypes = [{'libtype': 'static'}]
|
|
|
|
rec = {'name': name, 'toolchain-options': opts, 'libtypes': libtypes}
|
|
if files:
|
|
rec['files'] = files
|
|
if selector:
|
|
rec['selector'] = selector
|
|
if outdir:
|
|
rec['outdir'] = outdir
|
|
if noprefix:
|
|
rec['noprefix'] = noprefix
|
|
libs.append(rec)
|
|
|
|
|
|
def CalculatePintoolVar(name, params):
|
|
"""
|
|
Calculate the value of a $PINTOOL(os,x) or $PINTOOL(x) variable expansion.
|
|
|
|
@param name: The name "PINTOOL".
|
|
@type name: String.
|
|
@param params: Tuple containing the parameters of the $PINTOOL variable.
|
|
@type params: Tuple of strings.
|
|
|
|
@return: Value for the variable expansion.
|
|
@rtype: String.
|
|
"""
|
|
|
|
# If there is only 1 parameter, the "os" defaults to $HOSTOS. Return a
|
|
# string with the 2-parameter macro call. It will be re-expanded.
|
|
#
|
|
if len(params) == 1:
|
|
return '$PINTOOL($HOSTOS,' + params[0] + ')'
|
|
|
|
if len(params) != 2:
|
|
tsconsapi.Abort("$PINTOOL must take 1 or 2 parameters.")
|
|
|
|
os = params[0]
|
|
name = params[1]
|
|
if os == 'windows':
|
|
return name + '.dll'
|
|
if os == 'linux' or os == 'bsd':
|
|
return name + '.so'
|
|
if os == 'mac':
|
|
return name + '.dylib'
|
|
tsconsapi.Abort("Illegal OS value in '$PINTOOL(" + os + ", " + name + ")'.")
|
|
|
|
|
|
def IdentifyPinType(proj, pinhome):
|
|
"""
|
|
Identify the type of the Pin home area.
|
|
|
|
@param proj: Handle to a TSCons project.
|
|
@type proj: Unspecified handle type.
|
|
@param pinhome: Pathname to the Pin home area, relative to the project directory.
|
|
@type pinhome: String.
|
|
|
|
@return: Either 'kit', 'source', or '' telling the type of the Pin home area.
|
|
The empty string means we can't tell.
|
|
@rtype: String.
|
|
"""
|
|
|
|
pinhomeRoot = tsconsapi.TranslateProjRelativeToRootRelative(proj, pinhome)
|
|
|
|
try:
|
|
files = os.listdir(pinhomeRoot)
|
|
except:
|
|
return ''
|
|
|
|
if 'source' in files and 'extras' in files:
|
|
return 'kit'
|
|
if 'PinTools' in files and 'Misc' in files and 'External' in files:
|
|
return 'source'
|
|
return ''
|
|
|
|
|
|
def ApplyPintoolsToSource(pinhome, pintools, includes, defines, libs):
|
|
"""
|
|
Process PINTOOLS for a Pin source tree.
|
|
|
|
@param pinhome: Pathname to the Pin source tree, relative to the project directory.
|
|
@type pinhome: String.
|
|
@param pintools: PINTOOLS section of project file.
|
|
@type pintools: List.
|
|
@param includes: INCLUDES section of project file.
|
|
@type includes: List.
|
|
@param defines: DEFINES section of project file.
|
|
@type defines: List.
|
|
@param libs: LIBRARIES section of project file.
|
|
@type libs: List.
|
|
"""
|
|
|
|
includes.append({'dir': pinhome + '/PinTools/Include'})
|
|
includes.append({'dir': pinhome + '/PinTools/InstLib'})
|
|
includes.append({'dir': pinhome + '/build/Source/xed/xed-gcc-pin-$TARGETOS-$TARGETCPU/xed-kit/include/xed',
|
|
'selector': sel.TargetLinuxX86 + ' or ' + sel.TargetBsdX86})
|
|
includes.append({'dir': pinhome + '/build/Source/xed/xed-clang-pin-$TARGETOS-$TARGETCPU/xed-kit/include/xed', 'selector': sel.TargetMacX86})
|
|
includes.append({'dir': pinhome + '/build/Source/xed/xed-msvc-pin-$TARGETOS-$TARGETCPU/xed-kit/include/xed', 'selector': sel.TargetWindowsX86})
|
|
includes.append({'dir': pinhome + '/Source/atomic/00-export-include'})
|
|
includes.append({'dir': pinhome + '/Source/barecrt/00-export-include', 'selector': sel.TargetUnix})
|
|
includes.append({'dir': pinhome + '/Source/os-apis/00-export-include'})
|
|
includes.append({'dir': pinhome + '/Source/sync/00-export-include'})
|
|
includes.append({'dir': pinhome + '/Source/util/00-export-include'})
|
|
includes.append({'dir': pinhome + '/build/Source/pin/internal-include-$TARGETOS-ia32',
|
|
'selector': "not " + sel.BuildIntel64})
|
|
includes.append({'dir': pinhome + '/build/Source/pin/internal-include-$TARGETOS-intel64',
|
|
'selector': sel.BuildIntel64})
|
|
|
|
ApplyCommonDefines(defines)
|
|
|
|
for tool in pintools:
|
|
if not 'name' in tool:
|
|
tsconsapi.Abort("PINTOOLS element must contain 'name'.")
|
|
name = tool['name']
|
|
files = tool.get('files', [])
|
|
opts = tool.get('toolchain-options', [])
|
|
selector = tool.get('selector', None)
|
|
outdir = tool.get('outdir', None)
|
|
|
|
files.append({'library': pinhome + '/build/Source/pin/pin-$TARGETOS-$TARGETCPU/$LIB_STATIC($HOSTOS,pin)'})
|
|
files.append({'library': pinhome + '/build/Source/xed/xed-gcc-pin-$TARGETOS-$TARGETCPU/xed-kit/lib/libxed.a',
|
|
'selector': sel.TargetLinuxX86 + ' or ' + sel.TargetBsdX86})
|
|
files.append({'library': pinhome + '/build/Source/xed/xed-clang-pin-$TARGETOS-$TARGETCPU/xed-kit/lib/libxed.a', 'selector': sel.TargetMacX86})
|
|
files.append({'library': pinhome + '/build/Source/xed/xed-msvc-pin-$TARGETOS-$TARGETCPU/xed-kit/lib/xed.lib', 'selector': sel.TargetWindowsX86})
|
|
|
|
|
|
files.append({'library': pinhome + '/External/pindwarf/$(TARGETOS)/$(TARGETCPU)/libpindwarf.a', 'selector': sel.TargetLinux})
|
|
|
|
files.append({'library': pinhome + '/build/Source/pin/pin-$TARGETOS-$TARGETCPU/pinvm.lib', 'selector': sel.TargetWindows})
|
|
files.append({'library': pinhome + '/External/Ntdll/Lib_ia32_windows/ntdll-32.lib', 'selector': sel.TargetWindowsIA32})
|
|
files.append({'library': pinhome + '/External/Ntdll/Lib_intel64_windows/ntdll-64.lib', 'selector': sel.TargetWindowsIntel64})
|
|
|
|
opts.append({'option': 'linker_flags=-Wl,--version-script=$PATH(' + pinhome + '/PinTools/Include/pintool.ver)',
|
|
'selector': sel.TargetLinux + ' or ' + sel.TargetBsd})
|
|
opts.append({'option': 'linker_flags=-Wl,-exported_symbols_list -Wl,$PATH(' + pinhome + '/PinTools/Include/pintool.exp)',
|
|
'selector': sel.TargetMac})
|
|
|
|
ApplyCommonFiles(files)
|
|
ApplyCommonOptionsForPinToolsAndLibraries(opts)
|
|
ApplyCommonOptionsForPinTools(opts)
|
|
|
|
rec = {'name': name, 'noprefix': True, 'files': files, 'toolchain-options': opts, 'libtypes': [{'libtype': 'shared'}]}
|
|
if selector:
|
|
rec['selector'] = selector
|
|
if outdir:
|
|
rec['outdir'] = outdir
|
|
libs.append(rec)
|
|
|
|
|
|
def ApplyPintoolsToKit(pinhome, pintools, includes, defines, libs):
|
|
"""
|
|
Process PINTOOLS for a Pin kit tree.
|
|
|
|
@param pinhome: Pathname to the Pin kit, relative to the project directory.
|
|
@type pinhome: String.
|
|
@param pintools: PINTOOLS section of project file.
|
|
@type pintools: List.
|
|
@param includes: INCLUDES section of project file.
|
|
@type includes: List.
|
|
@param defines: DEFINES section of project file.
|
|
@type defines: List.
|
|
@param libs: LIBRARIES section of project file.
|
|
@type libs: List.
|
|
"""
|
|
|
|
includes.append({'dir': pinhome + '/source/include/pin'})
|
|
includes.append({'dir': pinhome + '/source/include/pin/gen'})
|
|
includes.append({'dir': pinhome + '/extras/xed-$TARGETCPU/include/xed', 'selector': sel.TargetX86})
|
|
includes.append({'dir': pinhome + '/extras/components/include'})
|
|
includes.append({'dir': pinhome + '/source/tools/InstLib'})
|
|
|
|
ApplyCommonDefines(defines)
|
|
|
|
for tool in pintools:
|
|
if not 'name' in tool:
|
|
tsconsapi.Abort("PINTOOLS element must contain 'name'.")
|
|
name = tool['name']
|
|
files = tool.get('files', [])
|
|
opts = tool.get('toolchain-options', [])
|
|
selector = tool.get('selector', None)
|
|
outdir = tool.get('outdir', None)
|
|
|
|
files.append({'library': pinhome + '/$TARGETCPU/lib/$LIB_STATIC($HOSTOS,pin)'})
|
|
files.append({'library': pinhome + '/extras/xed-$TARGETCPU/lib/libxed.a', 'selector': sel.TargetUnixX86})
|
|
files.append({'library': pinhome + '/extras/xed-$TARGETCPU/lib/xed.lib', 'selector': sel.TargetWindowsX86})
|
|
|
|
files.append({'library': pinhome + '/External/pindwarf/$(TARGETOS)/$(TARGETCPU)/libpindwarf.a', 'selector': sel.TargetLinux})
|
|
|
|
files.append({'library': pinhome + '/$TARGETCPU/lib/pinvm.lib', 'selector': sel.TargetWindows})
|
|
files.append({'library': pinhome + '/$TARGETCPU/lib-ext/ntdll-32.lib', 'selector': sel.TargetWindowsIA32})
|
|
files.append({'library': pinhome + '/$TARGETCPU/lib-ext/ntdll-64.lib', 'selector': sel.TargetWindowsIntel64})
|
|
|
|
# On Unix targets, limit the symbols that are exported from the tool's shared library.
|
|
#
|
|
opts.append({'option': 'linker_flags=-Wl,--version-script=$PATH(' + pinhome + '/source/include/pin/pintool.ver)',
|
|
'selector': sel.TargetLinux + ' or ' + sel.TargetBsd})
|
|
opts.append({'option': 'linker_flags=-Wl,-exported_symbols_list -Wl,$PATH(' + pinhome + '/source/include/pin/pintool.exp)',
|
|
'selector': sel.TargetMac})
|
|
|
|
ApplyCommonFiles(files)
|
|
ApplyCommonOptionsForPinToolsAndLibraries(opts)
|
|
ApplyCommonOptionsForPinTools(opts)
|
|
|
|
rec = {'name': name, 'noprefix': True, 'files': files, 'toolchain-options': opts, 'libtypes': [{'libtype': 'shared'}]}
|
|
if selector:
|
|
rec['selector'] = selector
|
|
if outdir:
|
|
rec['outdir'] = outdir
|
|
libs.append(rec)
|
|
|
|
|
|
def ApplyCommonDefines(defines):
|
|
"""
|
|
Add content to the project's DEFINES section that is common for all Pin types.
|
|
|
|
@param defines: DEFINES section of project file.
|
|
@type defines: List.
|
|
"""
|
|
|
|
defines.append({'macro': 'HOST_IA32', 'selector': sel.HostIA32})
|
|
defines.append({'macro': 'HOST_IA32E', 'selector': sel.HostIntel64})
|
|
defines.append({'macro': 'TARGET_IA32', 'selector': sel.TargetIA32})
|
|
defines.append({'macro': 'TARGET_IA32E', 'selector': sel.TargetIntel64})
|
|
defines.append({'macro': 'TARGET_LINUX', 'selector': sel.TargetLinux})
|
|
defines.append({'macro': 'TARGET_WINDOWS', 'selector': sel.TargetWindows})
|
|
defines.append({'macro': 'TARGET_MAC', 'selector': sel.TargetMac})
|
|
defines.append({'macro': 'TARGET_BSD', 'selector': sel.TargetBsd})
|
|
|
|
|
|
def ApplyCommonFiles(files):
|
|
"""
|
|
Add content to the 'files' list for a Pin tool that is common for all Pin types.
|
|
|
|
@param files: File list for a Pin tool.
|
|
@param files: List.
|
|
"""
|
|
|
|
# These libraries are found using the default library search path on Windows.
|
|
#
|
|
files.append({'library-from-path': 'libcpmt.lib', 'selector': sel.TargetWindows})
|
|
files.append({'library-from-path': 'libcmt.lib', 'selector': sel.TargetWindows})
|
|
files.append({'library-from-path': 'kernel32.lib', 'selector': sel.TargetWindows})
|
|
|
|
|
|
def ApplyCommonOptionsForPinToolsAndLibraries(opts):
|
|
"""
|
|
Add content to the 'toolchain-options' list for a Pin tool or library.
|
|
|
|
@param opts: Option list for a Pin tool.
|
|
@type opts: List.
|
|
"""
|
|
|
|
opts.append({'option': 'pinflags=1'})
|
|
|
|
# Tools on IA32 Linux and BSD are not compiled PIC even though they are shared libraries.
|
|
# The reason for this is that the compiler generates a call to a small thunk to materialize
|
|
# the PC for PIC code. If this call occurs in an analysis routine, it prevents Pin from
|
|
# inlining the routine. Therefore, we disable PIC as an optimization. Instead, the linker
|
|
# will generate dynamic relocations to compensate for any non-PIC code.
|
|
#
|
|
# We only do this on IA32 because on Intel64, the compiler doesn't need to generate the
|
|
# thunk calls to materialize the PC. Also, the Intel64 linker doesn't support dynamic
|
|
# relocations to compensate for non-PIC code.
|
|
#
|
|
# We don't do this on macOS* because non-PIC shared libraries are not supported on that
|
|
# platform. As a result, IA32 tools that reference global variables will contain a call
|
|
# to the thunk, and this will prevent them from being inlined.
|
|
#
|
|
opts.append({'option': 'nopic=1', 'selector': sel.TargetLinuxIA32 + ' or ' + sel.TargetBsdIA32})
|
|
|
|
|
|
def ApplyCommonOptionsForPinTools(opts):
|
|
"""
|
|
Add content to the 'toolchain-options' list for a Pin tool that is common for all
|
|
Pin types.
|
|
|
|
@param opts: Option list for a Pin tool.
|
|
@type opts: List.
|
|
"""
|
|
|
|
# This ensures that the tool uses global symbols defined in its own shared library before
|
|
# resolving to symbols defined in Pin.
|
|
#
|
|
opts.append({'option': 'linker_flags=-Wl,-Bsymbolic', 'selector': sel.TargetLinux + ' or ' + sel.TargetBsd})
|
|
|
|
opts.append({'option': 'linker_nostdlib=1', 'selector': sel.TargetWindows})
|
|
opts.append({'option': 'linker_export=main', 'selector': sel.TargetWindows})
|
|
opts.append({'option': 'linker_entry=Ptrace_DllMainCRTStartup@12', 'selector': sel.TargetWindowsIA32})
|
|
opts.append({'option': 'linker_entry=Ptrace_DllMainCRTStartup', 'selector': sel.TargetWindowsIntel64})
|
|
opts.append({'option': 'linker_base=0x55000000', 'selector': sel.TargetWindowsIA32})
|
|
opts.append({'option': 'linker_base=0xC5000000', 'selector': sel.TargetWindowsIntel64})
|
|
|
|
|
|
def GetPinPath(proj, pinHome, pinType):
|
|
"""
|
|
Get the pathname to the Pin launcher.
|
|
|
|
@param proj: Handle to a TSCons project.
|
|
@type proj: Unspecified handle type.
|
|
@param pinHome: The value of PINHOME.
|
|
@type pinHome: String.
|
|
@param pinType: Either "kit" or "source", depending on what PINHOME refers to.
|
|
@type pinType: String.
|
|
|
|
@return: Pathname to the Pin launcher, relative to the project file or absolute.
|
|
@rtype: String.
|
|
"""
|
|
|
|
cpu = tsconsapi.SubstituteVariables(proj, '$TARGETCPU')
|
|
os = tsconsapi.SubstituteVariables(proj, '$TARGETOS')
|
|
|
|
# This is the Pin launcher in all Pin kits.
|
|
#
|
|
if pinType == 'kit':
|
|
if os == 'windows':
|
|
return pinHome + '/pin.bat'
|
|
else:
|
|
return pinHome + '/pin'
|
|
|
|
# When building out of a source tree, we use these scripts to launch
|
|
# Pin on systems where the tool links against shared libraries.
|
|
# The script sets the library load path to find the libraries in
|
|
# the source tree.
|
|
#
|
|
if os == 'linux' and cpu == 'ia32':
|
|
return pinHome + '/Source/pin/pin-runner-linux-ia32.sh'
|
|
if os == 'linux' and cpu == 'intel64':
|
|
return pinHome + '/Source/pin/pin-runner-linux-intel64.sh'
|
|
|
|
# On systems where the tool does not link against shared libraries, we
|
|
# can invoke the Pin binary directly.
|
|
#
|
|
if os == 'windows':
|
|
return pinHome + '/build/Source/pin/pin-' + os + '-' + cpu + '/pin.exe'
|
|
else:
|
|
return pinHome + '/build/Source/pin/pin-' + os + '-' + cpu + '/pin'
|