зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound.
This commit is contained in:
Коммит
5cc26e47b1
|
@ -124,7 +124,7 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$MOZ_DISABLE_ICF" -a -z "$DEVELOPE
|
|||
# the same address
|
||||
if AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS -Wl,--icf=safe -ffunction-sections conftest.${ac_ext} $LIBS 1>&2]) &&
|
||||
test -s conftest${ac_exeext} &&
|
||||
$LLVM_OBJDUMP -t conftest${ac_exeext} | awk changequote(<<, >>)'{a[<<$>>6] = <<$>>1} END {if (a["foo"] && (a["foo"] != a["bar"])) { exit 1 }}'changequote([, ]); then
|
||||
objdump -t conftest${ac_exeext} | awk changequote(<<, >>)'{a[<<$>>6] = <<$>>1} END {if (a["foo"] && (a["foo"] != a["bar"])) { exit 1 }}'changequote([, ]); then
|
||||
LD_SUPPORTS_ICF=yes
|
||||
else
|
||||
LD_SUPPORTS_ICF=no
|
||||
|
|
|
@ -9,9 +9,6 @@ include('checks.configure')
|
|||
|
||||
# Make `toolkit` available when toolkit/moz.configure is not included.
|
||||
toolkit = dependable(None)
|
||||
# Likewise with `bindgen_config_paths` when
|
||||
# build/moz.configure/bindgen.configure is not included.
|
||||
bindgen_config_paths = dependable(None)
|
||||
|
||||
option(env='DIST', nargs=1, help='DIST directory')
|
||||
|
||||
|
|
|
@ -583,31 +583,6 @@ set_config('MAKENSISU_FLAGS', nsis_flags)
|
|||
|
||||
check_prog('7Z', ('7z', '7za'), allow_missing=True, when=target_is_windows)
|
||||
|
||||
|
||||
@depends(c_compiler, bindgen_config_paths)
|
||||
def llvm_objdump(c_compiler, bindgen_config_paths):
|
||||
clang = None
|
||||
if c_compiler and c_compiler.type == 'clang':
|
||||
clang = c_compiler.compiler
|
||||
elif c_compiler and c_compiler.type == 'clang-cl':
|
||||
clang = os.path.join(os.path.dirname(c_compiler.compiler), 'clang')
|
||||
elif bindgen_config_paths:
|
||||
clang = bindgen_config_paths.clang_path
|
||||
llvm_objdump = 'llvm-objdump'
|
||||
if clang:
|
||||
out = check_cmd_output(clang, '--print-prog-name=llvm-objdump',
|
||||
onerror=lambda: None)
|
||||
if out:
|
||||
llvm_objdump = out.rstrip()
|
||||
return (llvm_objdump,)
|
||||
|
||||
|
||||
llvm_objdump = check_prog('LLVM_OBJDUMP', llvm_objdump, what='llvm-objdump',
|
||||
when='--enable-compile-environment')
|
||||
|
||||
add_old_configure_assignment('LLVM_OBJDUMP', llvm_objdump)
|
||||
|
||||
|
||||
# Please do not add configure checks from here on.
|
||||
|
||||
# Fallthrough to autoconf-based configure
|
||||
|
|
|
@ -6,7 +6,6 @@ from __future__ import print_function, unicode_literals
|
|||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
@ -18,7 +17,6 @@ from mozpack.executables import (
|
|||
get_type,
|
||||
ELF,
|
||||
MACHO,
|
||||
UNKNOWN,
|
||||
)
|
||||
|
||||
|
||||
|
@ -31,6 +29,7 @@ HOST = {
|
|||
buildconfig.substs.get('MOZ_LIBSTDCXX_HOST_VERSION'),
|
||||
'platform': buildconfig.substs['HOST_OS_ARCH'],
|
||||
'readelf': 'readelf',
|
||||
'nm': 'nm',
|
||||
}
|
||||
|
||||
TARGET = {
|
||||
|
@ -39,10 +38,10 @@ TARGET = {
|
|||
'platform': buildconfig.substs['OS_TARGET'],
|
||||
'readelf': '{}readelf'.format(
|
||||
buildconfig.substs.get('TOOLCHAIN_PREFIX', '')),
|
||||
'nm': '{}nm'.format(buildconfig.substs.get('TOOLCHAIN_PREFIX', '')),
|
||||
'readobj': '{}readobj'.format(buildconfig.substs.get('TOOLCHAIN_PREFIX', '')),
|
||||
}
|
||||
|
||||
ADDR_RE = re.compile(r'[0-9a-f]{8,16}')
|
||||
|
||||
if buildconfig.substs.get('HAVE_64BIT_BUILD'):
|
||||
GUESSED_NSMODULE_SIZE = 8
|
||||
else:
|
||||
|
@ -76,35 +75,11 @@ def at_least_one(iter):
|
|||
raise Empty()
|
||||
|
||||
|
||||
# Iterates the symbol table on ELF and MACHO, and the export table on
|
||||
# COFF/PE.
|
||||
def iter_symbols(binary):
|
||||
ty = get_type(binary)
|
||||
# XXX: Static libraries on ELF, MACHO and COFF/PE systems are all
|
||||
# ar archives. So technically speaking, the following is wrong
|
||||
# but is enough for now. llvm-objdump -t can actually be used on all
|
||||
# platforms for static libraries, but its format is different for
|
||||
# Windows .obj files, so the following won't work for them, but
|
||||
# it currently doesn't matter.
|
||||
if ty == UNKNOWN and open(binary).read(8) == '!<arch>\n':
|
||||
ty = ELF
|
||||
if ty in (ELF, MACHO):
|
||||
for line in get_output(buildconfig.substs['LLVM_OBJDUMP'], '-t',
|
||||
binary):
|
||||
m = ADDR_RE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
addr = int(m.group(0), 16)
|
||||
# The second "column" is 7 one-character items that can be
|
||||
# whitespaces. We don't have use for their value, so just skip
|
||||
# those.
|
||||
rest = line[m.end() + 9:].split()
|
||||
# The number of remaining colums will vary between ELF and MACHO.
|
||||
# On ELF, we have:
|
||||
# Section Size .hidden? Name
|
||||
# On Macho, the size is skipped.
|
||||
# In every case, the symbol name is last.
|
||||
name = rest[-1]
|
||||
def iter_readelf_symbols(target, binary):
|
||||
for line in get_output(target['readelf'], '-sW', binary):
|
||||
data = line.split()
|
||||
if len(data) >= 8 and data[0].endswith(':') and data[0][:-1].isdigit():
|
||||
n, addr, size, type, bind, vis, index, name = data[:8]
|
||||
if '@' in name:
|
||||
name, ver = name.rsplit('@', 1)
|
||||
while name.endswith('@'):
|
||||
|
@ -112,37 +87,16 @@ def iter_symbols(binary):
|
|||
else:
|
||||
ver = None
|
||||
yield {
|
||||
'addr': addr,
|
||||
'size': int(rest[1], 16) if ty == ELF else 0,
|
||||
'addr': int(addr, 16),
|
||||
# readelf output may contain decimal values or hexadecimal
|
||||
# values prefixed with 0x for the size. Let python autodetect.
|
||||
'size': int(size, 0),
|
||||
'type': type,
|
||||
'binding': bind,
|
||||
'visibility': vis,
|
||||
'index': index,
|
||||
'name': name,
|
||||
'version': ver or None,
|
||||
}
|
||||
else:
|
||||
export_table = False
|
||||
for line in get_output(buildconfig.substs['LLVM_OBJDUMP'], '-p',
|
||||
binary):
|
||||
if line.strip() == 'Export Table:':
|
||||
export_table = True
|
||||
continue
|
||||
elif not export_table:
|
||||
continue
|
||||
|
||||
cols = line.split()
|
||||
# The data we're interested in comes in 3 columns, and the first
|
||||
# column is a number.
|
||||
if len(cols) != 3 or not cols[0].isdigit():
|
||||
continue
|
||||
_, rva, name = cols
|
||||
# - The MSVC mangling has some type info following `@@`
|
||||
# - Any namespacing that can happen on the symbol appears as a
|
||||
# suffix, after a `@`.
|
||||
# - Mangled symbols are prefixed with `?`.
|
||||
name = name.split('@@')[0].split('@')[0].lstrip('?')
|
||||
yield {
|
||||
'addr': int(rva, 16),
|
||||
'size': 0,
|
||||
'name': name,
|
||||
'version': None,
|
||||
'version': ver,
|
||||
}
|
||||
|
||||
|
||||
|
@ -159,14 +113,14 @@ def check_dep_versions(target, binary, lib, prefix, max_version):
|
|||
unwanted = []
|
||||
prefix = prefix + '_'
|
||||
try:
|
||||
for sym in at_least_one(iter_symbols(binary)):
|
||||
if sym['addr'] == 0 and sym['version'] and \
|
||||
for sym in at_least_one(iter_readelf_symbols(target, binary)):
|
||||
if sym['index'] == 'UND' and sym['version'] and \
|
||||
sym['version'].startswith(prefix):
|
||||
version = Version(sym['version'][len(prefix):])
|
||||
if version > max_version:
|
||||
unwanted.append(sym)
|
||||
except Empty:
|
||||
raise RuntimeError('Could not parse llvm-objdump output?')
|
||||
raise RuntimeError('Could not parse readelf output?')
|
||||
if unwanted:
|
||||
raise RuntimeError('\n'.join([
|
||||
'We do not want these {} symbol versions to be used:'.format(lib)
|
||||
|
@ -218,23 +172,62 @@ def check_nsmodules(target, binary):
|
|||
if target is HOST or not is_libxul(binary):
|
||||
raise Skip()
|
||||
symbols = []
|
||||
for sym in iter_symbols(binary):
|
||||
if sym['addr'] == 0:
|
||||
continue
|
||||
name = sym['name']
|
||||
# NSModules symbols end with _NSModule or _NSModuleE when C++-mangled.
|
||||
if name.endswith(('_NSModule', '_NSModuleE')):
|
||||
# We don't have a valid size in the symbol list for macho and coff.
|
||||
# Use our guesstimate.
|
||||
size = sym['size'] or GUESSED_NSMODULE_SIZE
|
||||
symbols.append((sym['addr'], size, name))
|
||||
elif name in ('__start_kPStaticModules', '__stop_kPStaticModules'):
|
||||
# For coff, these symbols have a size.
|
||||
if get_type(binary) not in (ELF, MACHO):
|
||||
size = GUESSED_NSMODULE_SIZE
|
||||
else:
|
||||
size = 0
|
||||
symbols.append((sym['addr'], size, name))
|
||||
if buildconfig.substs.get('CC_TYPE') in ('msvc', 'clang-cl'):
|
||||
for line in get_output('dumpbin.exe', '-exports', binary):
|
||||
data = line.split(None, 3)
|
||||
if data and len(data) == 4 and data[0].isdigit() and \
|
||||
ishex(data[1]) and ishex(data[2]):
|
||||
# - Some symbols in the table can be aliases, and appear as
|
||||
# `foo = bar`.
|
||||
# - The MSVC mangling has some type info following `@@`
|
||||
# - Any namespacing that can happen on the symbol appears as a
|
||||
# suffix, after a `@`.
|
||||
# - Mangled symbols are prefixed with `?`.
|
||||
name = data[3].split(' = ')[0].split('@@')[0].split('@')[0] \
|
||||
.lstrip('?')
|
||||
if name.endswith('_NSModule') or name in (
|
||||
'__start_kPStaticModules',
|
||||
'__stop_kPStaticModules'):
|
||||
symbols.append((int(data[2], 16), GUESSED_NSMODULE_SIZE,
|
||||
name))
|
||||
else:
|
||||
# MinGW-Clang, when building pdbs, doesn't include the symbol table into
|
||||
# the final module. To get the NSModule info, we can look at the exported
|
||||
# symbols. (#1475562)
|
||||
if buildconfig.substs['OS_ARCH'] == 'WINNT' and \
|
||||
buildconfig.substs['HOST_OS_ARCH'] != 'WINNT':
|
||||
readobj_output = get_output(target['readobj'], '-coff-exports', binary)
|
||||
# Transform the output of readobj into nm-like output
|
||||
output = []
|
||||
for line in readobj_output:
|
||||
if "Name" in line:
|
||||
name = line.replace("Name:", "").strip()
|
||||
elif "RVA" in line:
|
||||
rva = line.replace("RVA:", "").strip()
|
||||
output.append("%s r %s" % (name, rva))
|
||||
else:
|
||||
output = get_output(target['nm'], '-P', binary)
|
||||
|
||||
for line in output:
|
||||
data = line.split()
|
||||
# Some symbols may not have a size listed at all.
|
||||
if len(data) == 3:
|
||||
data.append('0')
|
||||
if len(data) == 4:
|
||||
sym, _, addr, size = data
|
||||
# NSModules symbols end with _NSModule or _NSModuleE when
|
||||
# C++-mangled.
|
||||
if sym.endswith(('_NSModule', '_NSModuleE')):
|
||||
# On mac, nm doesn't actually print anything other than 0
|
||||
# for the size. So take our best guess.
|
||||
size = int(size, 16) or GUESSED_NSMODULE_SIZE
|
||||
symbols.append((int(addr, 16), size, sym))
|
||||
elif sym.endswith(('__start_kPStaticModules',
|
||||
'__stop_kPStaticModules')):
|
||||
# On ELF and mac systems, these symbols have no size, such
|
||||
# that the first actual NSModule has the same address as
|
||||
# the start symbol.
|
||||
symbols.append((int(addr, 16), 0, sym))
|
||||
if not symbols:
|
||||
raise RuntimeError('Could not find NSModules')
|
||||
|
||||
|
|
|
@ -19,8 +19,33 @@ from mozpack.executables import (
|
|||
)
|
||||
from buildconfig import substs
|
||||
|
||||
def dependentlibs_win32_objdump(lib):
|
||||
proc = subprocess.Popen([substs['LLVM_OBJDUMP'], '--private-headers', lib], stdout = subprocess.PIPE)
|
||||
def dependentlibs_dumpbin(lib):
|
||||
'''Returns the list of dependencies declared in the given DLL'''
|
||||
try:
|
||||
proc = subprocess.Popen(['dumpbin', '-dependents', lib], stdout = subprocess.PIPE)
|
||||
except OSError:
|
||||
# dumpbin is missing, probably mingw compilation. Try using objdump.
|
||||
return dependentlibs_mingw_objdump(lib)
|
||||
deps = []
|
||||
for line in proc.stdout:
|
||||
# Each line containing an imported library name starts with 4 spaces
|
||||
match = re.match(' (\S+)', line)
|
||||
if match:
|
||||
deps.append(match.group(1))
|
||||
elif len(deps):
|
||||
# There may be several groups of library names, but only the
|
||||
# first one is interesting. The second one is for delayload-ed
|
||||
# libraries.
|
||||
break
|
||||
proc.wait()
|
||||
return deps
|
||||
|
||||
def dependentlibs_mingw_objdump(lib):
|
||||
try:
|
||||
proc = subprocess.Popen(['objdump', '-x', lib], stdout = subprocess.PIPE)
|
||||
except OSError:
|
||||
# objdump is missing, try using llvm-objdump.
|
||||
proc = subprocess.Popen(['llvm-objdump', '-private-headers', lib], stdout = subprocess.PIPE)
|
||||
deps = []
|
||||
for line in proc.stdout:
|
||||
match = re.match('\s+DLL Name: (\S+)', line)
|
||||
|
@ -29,27 +54,35 @@ def dependentlibs_win32_objdump(lib):
|
|||
proc.wait()
|
||||
return deps
|
||||
|
||||
def dependentlibs_elf_objdump(lib):
|
||||
def dependentlibs_readelf(lib):
|
||||
'''Returns the list of dependencies declared in the given ELF .so'''
|
||||
proc = subprocess.Popen([substs['LLVM_OBJDUMP'], '--private-headers', lib], stdout = subprocess.PIPE)
|
||||
proc = subprocess.Popen([substs.get('TOOLCHAIN_PREFIX', '') + 'readelf', '-d', lib], stdout = subprocess.PIPE)
|
||||
deps = []
|
||||
for line in proc.stdout:
|
||||
# We are looking for lines with the format:
|
||||
# NEEDED libname
|
||||
tmp = line.split()
|
||||
if len(tmp) == 2 and tmp[0] == 'NEEDED':
|
||||
deps.append(tmp[1])
|
||||
# Each line has the following format:
|
||||
# tag (TYPE) value
|
||||
# or with BSD readelf:
|
||||
# tag TYPE value
|
||||
# Looking for NEEDED type entries
|
||||
tmp = line.split(' ', 3)
|
||||
if len(tmp) > 3 and 'NEEDED' in tmp[2]:
|
||||
# NEEDED lines look like:
|
||||
# 0x00000001 (NEEDED) Shared library: [libname]
|
||||
# or with BSD readelf:
|
||||
# 0x00000001 NEEDED Shared library: [libname]
|
||||
match = re.search('\[(.*)\]', tmp[3])
|
||||
if match:
|
||||
deps.append(match.group(1))
|
||||
proc.wait()
|
||||
return deps
|
||||
|
||||
def dependentlibs_mac_objdump(lib):
|
||||
def dependentlibs_otool(lib):
|
||||
'''Returns the list of dependencies declared in the given MACH-O dylib'''
|
||||
proc = subprocess.Popen([substs['LLVM_OBJDUMP'], '--private-headers', lib], stdout = subprocess.PIPE)
|
||||
deps = []
|
||||
proc = subprocess.Popen([substs['OTOOL'], '-l', lib], stdout = subprocess.PIPE)
|
||||
deps= []
|
||||
cmd = None
|
||||
for line in proc.stdout:
|
||||
# llvm-objdump --private-headers output contains many different
|
||||
# things. The interesting data
|
||||
# otool -l output contains many different things. The interesting data
|
||||
# is under "Load command n" sections, with the content:
|
||||
# cmd LC_LOAD_DYLIB
|
||||
# cmdsize 56
|
||||
|
@ -90,13 +123,13 @@ def gen_list(output, lib):
|
|||
libpaths = [os.path.join(substs['DIST'], 'bin')]
|
||||
binary_type = get_type(lib)
|
||||
if binary_type == ELF:
|
||||
func = dependentlibs_elf_objdump
|
||||
func = dependentlibs_readelf
|
||||
elif binary_type == MACHO:
|
||||
func = dependentlibs_mac_objdump
|
||||
func = dependentlibs_otool
|
||||
else:
|
||||
ext = os.path.splitext(lib)[1]
|
||||
assert(ext == '.dll')
|
||||
func = dependentlibs_win32_objdump
|
||||
func = dependentlibs_dumpbin
|
||||
|
||||
deps = dependentlibs(lib, libpaths, func)
|
||||
base_lib = mozpath.basename(lib)
|
||||
|
|
Загрузка…
Ссылка в новой задаче