From b108d42040b6ec1dc06086fb0b2b0fe0aea1cf13 Mon Sep 17 00:00:00 2001 From: Omair Majid Date: Jan 19 2018 20:23:25 +0000 Subject: Verify debug info and fix build on clang 5 --- diff --git a/check-debug-symbols.py b/check-debug-symbols.py new file mode 100755 index 0000000..1e14800 --- /dev/null +++ b/check-debug-symbols.py @@ -0,0 +1,136 @@ +#!/usr/bin/python3 + +""" +Check debug symbols are present in shared object and can identify +code. + +It starts scanning from a directory and recursively scans all ELF +files found in it for various symbols to ensure all debuginfo is +present and nothing has been stripped. + +Usage: + +./check-debug-symbols /path/of/dir/to/scan/ + + +Example: + +./check-debug-symbols /usr/lib64 +""" + +# This technique was explained to me by Mark Wielaard (mjw). + +import collections +import os +import re +import subprocess +import sys + +ScanResult = collections.namedtuple('ScanResult', + 'file_name debug_info debug_abbrev file_symbols gnu_debuglink') + + +def scan_file(file): + "Scan the provided file and return a ScanResult containing results of the scan." + + # Test for .debug_* sections in the shared object. This is the main test. + # Stripped objects will not contain these. + readelf_S_result = subprocess.run(['eu-readelf', '-S', file], + stdout=subprocess.PIPE, encoding='utf-8', check=True) + has_debug_info = any(line for line in readelf_S_result.stdout.split('\n') if '] .debug_info' in line) + + has_debug_abbrev = any(line for line in readelf_S_result.stdout.split('\n') if '] .debug_abbrev' in line) + + # Test FILE symbols. These will most likely be removed by anyting that + # manipulates symbol tables because it's generally useless. So a nice test + # that nothing has messed with symbols. + def contains_file_symbols(line): + parts = line.split() + if len(parts) < 8: + return False + return \ + parts[2] == '0' and parts[3] == 'FILE' and parts[4] == 'LOCAL' and parts[5] == 'DEFAULT' and \ + parts[6] == 'ABS' and re.match(r'((.*/)?[-_a-zA-Z0-9]+\.(c|cc|cpp|cxx))?', parts[7]) + + readelf_s_result = subprocess.run(["eu-readelf", '-s', file], + stdout=subprocess.PIPE, encoding='utf-8', check=True) + has_file_symbols = any(line for line in readelf_s_result.stdout.split('\n') if contains_file_symbols(line)) + + # Test that there are no .gnu_debuglink sections pointing to another + # debuginfo file. There shouldn't be any debuginfo files, so the link makes + # no sense either. + has_gnu_debuglink = any(line for line in readelf_s_result.stdout.split('\n') if '] .gnu_debuglink' in line) + + return ScanResult(file, has_debug_info, has_debug_abbrev, has_file_symbols, has_gnu_debuglink) + +def is_elf(file): + result = subprocess.run(['file', file], stdout=subprocess.PIPE, encoding='utf-8', check=True) + return re.search('ELF 64-bit LSB (?:executable|shared object)', result.stdout) + +def scan_file_if_sensible(file): + if is_elf(file): + # print(file) + return scan_file(file) + return None + +def scan_dir(dir): + results = [] + for root, _, files in os.walk(dir): + for name in files: + result = scan_file_if_sensible(os.path.join(root, name)) + if result: + results.append(result) + return results + +def scan(file): + file = os.path.abspath(file) + if os.path.isdir(file): + return scan_dir(file) + elif os.path.isfile(file): + return scan_file_if_sensible(file) + +def is_bad_result(result): + return not result.debug_info or not result.debug_abbrev or not result.file_symbols or result.gnu_debuglink + +def print_scan_results(results, verbose): + # print(results) + for result in results: + file_name = result.file_name + found_issue = False + if not result.debug_info: + found_issue = True + print('error: missing .debug_info section in', file_name) + if not result.debug_abbrev: + found_issue = True + print('error: missing .debug_abbrev section in', file_name) + if not result.file_symbols: + found_issue = True + print('error: missing FILE symbols in', file_name) + if result.gnu_debuglink: + found_issue = True + print('error: unexpected .gnu_debuglink section in', file_name) + if verbose and not found_issue: + print('OK: ', file_name) + +def main(args): + verbose = False + files = [] + for arg in args: + if arg == '--verbose' or arg == '-v': + verbose = True + else: + files.append(arg) + + results = [] + for file in files: + results.extend(scan(file)) + + print_scan_results(results, verbose) + + if any(is_bad_result(result) for result in results): + return 1 + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/coreclr-clang5.patch b/coreclr-clang5.patch new file mode 100644 index 0000000..c446b57 --- /dev/null +++ b/coreclr-clang5.patch @@ -0,0 +1,40 @@ +commit 9b22e1a767dee38f351001c5601f56d78766a43e +Author: Sergey Andreenko +Date: Mon Dec 11 19:05:15 2017 -0800 + + fix CoreCLR build errors with clang5.0. (#15477) + + * spmi: delete the explicit call to the constructor. + + MethodContext was already initialized through `new MethodContext();` + + * add an artificial using of lambda param. + + the define `#define PAL_EXCEPT(dispositionExpression)` + can declare expression that has zero or one param. If it has zero param, then `__param` in the lambda is unused, prevent clang complains by adding this change. + +diff --git dotnet/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp dotnet/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +index 581b2286d8..601f73833e 100644 +--- dotnet/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp ++++ dotnet/src/coreclr/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +@@ -299,8 +299,6 @@ void MethodContext::MethodInitHelperFile(HANDLE hFile) + + void MethodContext::MethodInitHelper(unsigned char* buff2, unsigned int totalLen) + { +- MethodContext::MethodContext(); +- + unsigned int buffIndex = 0; + unsigned int localsize = 0; + unsigned char canary = 0xff; +diff --git dotnet/src/coreclr/src/pal/inc/pal.h dotnet/src/coreclr/src/pal/inc/pal.h +index 8f6bc12798..e8fdab544f 100644 +--- dotnet/src/coreclr/src/pal/inc/pal.h ++++ dotnet/src/coreclr/src/pal/inc/pal.h +@@ -5921,6 +5921,7 @@ public: + EXCEPTION_DISPOSITION disposition = EXCEPTION_CONTINUE_EXECUTION; \ + auto exceptionFilter = [&disposition, &__param](PAL_SEHException& ex) \ + { \ ++ (void)__param; \ + disposition = dispositionExpression; \ + _ASSERTE(disposition != EXCEPTION_CONTINUE_EXECUTION); \ + return disposition; \ diff --git a/corefx-less-warnings.patch b/corefx-less-warnings.patch new file mode 100644 index 0000000..2784d6c --- /dev/null +++ b/corefx-less-warnings.patch @@ -0,0 +1,10 @@ +--- dotnet/src/corefx/src/Native/Unix/CMakeLists.txt ++++ dotnet/src/corefx/src/Native/Unix/CMakeLists.txt +@@ -15,6 +15,7 @@ + add_compile_options(-Wno-disabled-macro-expansion) + add_compile_options(-Wno-c++98-compat) + add_compile_options(-Wno-c++98-compat-pedantic) ++add_compile_options(-Wno-zero-as-null-pointer-constant) + add_compile_options(-Werror) + add_compile_options(-fPIC) + add_compile_options(-I${CMAKE_CURRENT_SOURCE_DIR}/Common) diff --git a/dotnet.spec b/dotnet.spec index a421c1b..d97da34 100644 --- a/dotnet.spec +++ b/dotnet.spec @@ -5,7 +5,7 @@ Name: dotnet Summary: .NET Core CLI tools and run-time Version: %{runtime_version} -Release: 3%{?dist} +Release: 4%{?dist} URL: https://github.com/dotnet/ License: MIT and ASL 2.0 and BSD @@ -36,6 +36,8 @@ BuildRequires: openssl-devel Source0: https://omajid.fedorapeople.org/dotnet/dotnet-%{runtime_version}.tar.gz Source1: patch-nuget-packages.sh +Source2: check-debug-symbols.py + Patch0: missing-exec.patch # https://github.com/dotnet/coreclr/issues/13009 # https://github.com/dotnet/core-setup/pull/3129 @@ -43,6 +45,8 @@ Patch1: f27-libc.patch Patch2: corefx-not-portable.patch Patch3: do-not-strip-debuginfo.patch Patch4: fedora-rids.patch +Patch5: coreclr-clang5.patch +Patch6: corefx-less-warnings.patch %description .NET Core is a fast, lightweight and modular platform for creating @@ -106,6 +110,8 @@ cross platform applications that work on Linux, Mac and Windows. %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 +%patch6 -p1 %if 0%{?fedora} > 0 @@ -148,6 +154,12 @@ ln -s %{_libdir}/%{name}/dotnet %{buildroot}%{_bindir}/ install -d -m 0755 %{buildroot}%{_mandir}/man1/ find -iname 'dotnet*.1' -type f -exec cp {} %{buildroot}%{_mandir}/man1/ \; +# Check debug symbols in all elf objects. This is not in %%check +# because native binaries are stripped by rpm-build after %%install. +# So we need to do this check earlier. +echo "Testing build results for debug symbols..." +%{SOURCE2} -v %{buildroot}%{_libdir}/%{name}/ + %check %{buildroot}%{_libdir}/%{name}/dotnet --info @@ -171,6 +183,10 @@ find -iname 'dotnet*.1' -type f -exec cp {} %{buildroot}%{_mandir}/man1/ \; %doc %{_mandir}/man1/dotnet-*.1.gz %changelog +* Fri Jan 19 2018 Omair Majid - 2.0.3-4 +- Add a test script to sanity check debug and symbol info. +- Build with clang 5.0 + * Wed Nov 29 2017 Omair Majid - 2.0.3-3 - Add a Provides for 'dotnet' - Fix conditional macro