Skip to content

Commit

Permalink
Bug 603370 - Avoid Identical Code Folding messing with symbol reorder…
Browse files Browse the repository at this point in the history
…ing. r=khuey
  • Loading branch information
glandium committed Mar 8, 2012
1 parent 9648e0f commit 4c8468c
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 14 deletions.
8 changes: 7 additions & 1 deletion build/autoconf/compiler-opts.m4
Expand Up @@ -41,7 +41,13 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$MOZ_DISABLE_ICF"; then
fi
rm -rf conftest*])
if test "$LD_SUPPORTS_ICF" = yes; then
LDFLAGS="$LDFLAGS -Wl,--icf=safe"
_SAVE_LDFLAGS="$LDFLAGS -Wl,--icf=safe"
LDFLAGS="$LDFLAGS -Wl,--icf=safe -Wl,--print-icf-sections"
AC_TRY_LINK([], [],
[LD_PRINT_ICF_SECTIONS=-Wl,--print-icf-sections],
[LD_PRINT_ICF_SECTIONS=])
AC_SUBST([LD_PRINT_ICF_SECTIONS])
LDFLAGS="$_SAVE_LDFLAGS"
fi
fi
Expand Down
1 change: 1 addition & 0 deletions config/expandlibs_config.py.in
Expand Up @@ -55,3 +55,4 @@ IMPORT_LIB_SUFFIX = normalize_suffix("@IMPORT_LIB_SUFFIX@")
LIBS_DESC_SUFFIX = normalize_suffix("@LIBS_DESC_SUFFIX@")
EXPAND_LIBS_LIST_STYLE = "@EXPAND_LIBS_LIST_STYLE@"
EXPAND_LIBS_ORDER_STYLE = "@EXPAND_LIBS_ORDER_STYLE@"
LD_PRINT_ICF_SECTIONS = "@LD_PRINT_ICF_SECTIONS@"
40 changes: 39 additions & 1 deletion config/expandlibs_exec.py
Expand Up @@ -141,16 +141,54 @@ def makelist(self):
newlist = self[0:idx] + [ref] + [item for item in self[idx:] if item not in objs]
self[0:] = newlist

def _getFoldedSections(self):
'''Returns a dict about folded sections.
When section A and B are folded into section C, the dict contains:
{ 'A': 'C',
'B': 'C',
'C': ['A', 'B'] }'''
if not conf.LD_PRINT_ICF_SECTIONS:
return {}

proc = subprocess.Popen(self + [conf.LD_PRINT_ICF_SECTIONS], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
(stdout, stderr) = proc.communicate()
result = {}
# gold's --print-icf-sections output looks like the following:
# ld: ICF folding section '.section' in file 'file.o'into '.section' in file 'file.o'
# In terms of words, chances are this will change in the future,
# especially considering "into" is misplaced. Splitting on quotes
# seems safer.
for l in stderr.split('\n'):
quoted = l.split("'")
if len(quoted) > 5 and quoted[1] != quoted[5]:
result[quoted[1]] = quoted[5]
if quoted[5] in result:
result[quoted[5]].append(quoted[1])
else:
result[quoted[5]] = [quoted[1]]
return result

def _getOrderedSections(self, ordered_symbols):
'''Given an ordered list of symbols, returns the corresponding list
of sections following the order.'''
if not conf.EXPAND_LIBS_ORDER_STYLE in ['linkerscript', 'section-ordering-file']:
raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
finder = SectionFinder([arg for arg in self if isObject(arg) or os.path.splitext(arg)[1] == conf.LIB_SUFFIX])
folded = self._getFoldedSections()
sections = set()
ordered_sections = []
for symbol in ordered_symbols:
for section in finder.getSections(symbol):
symbol_sections = finder.getSections(symbol)
all_symbol_sections = []
for section in symbol_sections:
if section in folded:
if isinstance(folded[section], str):
section = folded[section]
all_symbol_sections.append(section)
all_symbol_sections.extend(folded[section])
else:
all_symbol_sections.append(section)
for section in all_symbol_sections:
if not section in sections:
ordered_sections.append(section)
sections.add(section)
Expand Down
53 changes: 43 additions & 10 deletions config/tests/unit-expandlibs.py
Expand Up @@ -268,11 +268,12 @@ def call(args, **kargs):
subprocess.call = subprocess_call

class FakeProcess(object):
def __init__(self, out):
def __init__(self, out, err = ''):
self.out = out
self.err = err

def communicate(self):
return (self.out, '')
return (self.out, self.err)

OBJDUMPS = {
'foo.o': '''
Expand All @@ -287,25 +288,31 @@ def communicate(self):
''',
}

class ObjdumpSubprocessPopen(object):
PRINT_ICF = '''
ld: ICF folding section '.text.hello' in file 'foo.o'into '.text.hi' in file 'bar.o'
ld: ICF folding section '.foo' in file 'foo.o'into '.foo' in file 'bar.o'
'''

class SubprocessPopen(object):
def __init__(self, test):
self.test = test

def __call__(self, args, stdout = None, stderr = None):
self.test.assertEqual(stdout, subprocess.PIPE)
self.test.assertEqual(stderr, subprocess.PIPE)
self.test.assertEqual(args[0], 'objdump')
self.test.assertEqual(args[1], '-t')
self.test.assertTrue(args[2] in OBJDUMPS)

return FakeProcess(OBJDUMPS[args[2]])
if args[0] == 'objdump':
self.test.assertEqual(args[1], '-t')
self.test.assertTrue(args[2] in OBJDUMPS)
return FakeProcess(OBJDUMPS[args[2]])
else:
return FakeProcess('', PRINT_ICF)

class TestSectionFinder(unittest.TestCase):
def test_getSections(self):
'''Test SectionFinder'''
# Divert subprocess.Popen
subprocess_popen = subprocess.Popen
subprocess.Popen = ObjdumpSubprocessPopen(self)
subprocess.Popen = SubprocessPopen(self)
config.EXPAND_LIBS_ORDER_STYLE = 'linkerscript'
config.OBJ_SUFFIX = '.o'
config.LIB_SUFFIX = '.a'
Expand All @@ -321,14 +328,40 @@ def test_getOrderedSections(self):
'''Test ExpandMoreArgs' _getOrderedSections'''
# Divert subprocess.Popen
subprocess_popen = subprocess.Popen
subprocess.Popen = ObjdumpSubprocessPopen(self)
subprocess.Popen = SubprocessPopen(self)
config.EXPAND_LIBS_ORDER_STYLE = 'linkerscript'
config.OBJ_SUFFIX = '.o'
config.LIB_SUFFIX = '.a'
config.LD_PRINT_ICF_SECTIONS = ''
args = ExpandArgsMore(['foo', '-bar', 'bar.o', 'foo.o'])
self.assertEqual(args._getOrderedSections(['_Z6foobarv', '_Z6barbazv']), ['.text._Z6foobarv', '.text._ZThn4_6foobarv', '.text.hot._Z6barbazv'])
self.assertEqual(args._getOrderedSections(['_ZThn4_6foobarv', '_Z6barbazv']), ['.text._Z6foobarv', '.text._ZThn4_6foobarv', '.text.hot._Z6barbazv'])
subprocess.Popen = subprocess_popen

def test_getFoldedSections(self):
'''Test ExpandMoreArgs' _getFoldedSections'''
# Divert subprocess.Popen
subprocess_popen = subprocess.Popen
subprocess.Popen = SubprocessPopen(self)
config.LD_PRINT_ICF_SECTIONS = '-Wl,--print-icf-sections'
args = ExpandArgsMore(['foo', '-bar', 'bar.o', 'foo.o'])
self.assertEqual(args._getFoldedSections(), {'.text.hello': '.text.hi', '.text.hi': ['.text.hello']})
subprocess.Popen = subprocess_popen

def test_getOrderedSectionsWithICF(self):
'''Test ExpandMoreArgs' _getOrderedSections, with ICF'''
# Divert subprocess.Popen
subprocess_popen = subprocess.Popen
subprocess.Popen = SubprocessPopen(self)
config.EXPAND_LIBS_ORDER_STYLE = 'linkerscript'
config.OBJ_SUFFIX = '.o'
config.LIB_SUFFIX = '.a'
config.LD_PRINT_ICF_SECTIONS = '-Wl,--print-icf-sections'
args = ExpandArgsMore(['foo', '-bar', 'bar.o', 'foo.o'])
self.assertEqual(args._getOrderedSections(['hello', '_Z6barbazv']), ['.text.hi', '.text.hello', '.text.hot._Z6barbazv'])
self.assertEqual(args._getOrderedSections(['_ZThn4_6foobarv', 'hi', '_Z6barbazv']), ['.text._Z6foobarv', '.text._ZThn4_6foobarv', '.text.hi', '.text.hello', '.text.hot._Z6barbazv'])
subprocess.Popen = subprocess_popen


if __name__ == '__main__':
unittest.main(testRunner=MozTestRunner())
8 changes: 7 additions & 1 deletion js/src/build/autoconf/compiler-opts.m4
Expand Up @@ -41,7 +41,13 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$MOZ_DISABLE_ICF"; then
fi
rm -rf conftest*])
if test "$LD_SUPPORTS_ICF" = yes; then
LDFLAGS="$LDFLAGS -Wl,--icf=safe"
_SAVE_LDFLAGS="$LDFLAGS -Wl,--icf=safe"
LDFLAGS="$LDFLAGS -Wl,--icf=safe -Wl,--print-icf-sections"
AC_TRY_LINK([], [],
[LD_PRINT_ICF_SECTIONS=-Wl,--print-icf-sections],
[LD_PRINT_ICF_SECTIONS=])
AC_SUBST([LD_PRINT_ICF_SECTIONS])
LDFLAGS="$_SAVE_LDFLAGS"
fi
fi
Expand Down
1 change: 1 addition & 0 deletions js/src/config/expandlibs_config.py.in
Expand Up @@ -55,3 +55,4 @@ IMPORT_LIB_SUFFIX = normalize_suffix("@IMPORT_LIB_SUFFIX@")
LIBS_DESC_SUFFIX = normalize_suffix("@LIBS_DESC_SUFFIX@")
EXPAND_LIBS_LIST_STYLE = "@EXPAND_LIBS_LIST_STYLE@"
EXPAND_LIBS_ORDER_STYLE = "@EXPAND_LIBS_ORDER_STYLE@"
LD_PRINT_ICF_SECTIONS = "@LD_PRINT_ICF_SECTIONS@"
40 changes: 39 additions & 1 deletion js/src/config/expandlibs_exec.py
Expand Up @@ -141,16 +141,54 @@ def makelist(self):
newlist = self[0:idx] + [ref] + [item for item in self[idx:] if item not in objs]
self[0:] = newlist

def _getFoldedSections(self):
'''Returns a dict about folded sections.
When section A and B are folded into section C, the dict contains:
{ 'A': 'C',
'B': 'C',
'C': ['A', 'B'] }'''
if not conf.LD_PRINT_ICF_SECTIONS:
return {}

proc = subprocess.Popen(self + [conf.LD_PRINT_ICF_SECTIONS], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
(stdout, stderr) = proc.communicate()
result = {}
# gold's --print-icf-sections output looks like the following:
# ld: ICF folding section '.section' in file 'file.o'into '.section' in file 'file.o'
# In terms of words, chances are this will change in the future,
# especially considering "into" is misplaced. Splitting on quotes
# seems safer.
for l in stderr.split('\n'):
quoted = l.split("'")
if len(quoted) > 5 and quoted[1] != quoted[5]:
result[quoted[1]] = quoted[5]
if quoted[5] in result:
result[quoted[5]].append(quoted[1])
else:
result[quoted[5]] = [quoted[1]]
return result

def _getOrderedSections(self, ordered_symbols):
'''Given an ordered list of symbols, returns the corresponding list
of sections following the order.'''
if not conf.EXPAND_LIBS_ORDER_STYLE in ['linkerscript', 'section-ordering-file']:
raise Exception('EXPAND_LIBS_ORDER_STYLE "%s" is not supported' % conf.EXPAND_LIBS_ORDER_STYLE)
finder = SectionFinder([arg for arg in self if isObject(arg) or os.path.splitext(arg)[1] == conf.LIB_SUFFIX])
folded = self._getFoldedSections()
sections = set()
ordered_sections = []
for symbol in ordered_symbols:
for section in finder.getSections(symbol):
symbol_sections = finder.getSections(symbol)
all_symbol_sections = []
for section in symbol_sections:
if section in folded:
if isinstance(folded[section], str):
section = folded[section]
all_symbol_sections.append(section)
all_symbol_sections.extend(folded[section])
else:
all_symbol_sections.append(section)
for section in all_symbol_sections:
if not section in sections:
ordered_sections.append(section)
sections.add(section)
Expand Down

0 comments on commit 4c8468c

Please sign in to comment.