<div dir="ltr">Thanks Hans, and sorry for being unavailable to deal with the fallout from this. Trying again this time in <a href="https://reviews.llvm.org/D22611">https://reviews.llvm.org/D22611</a>.</div><br><div class="gmail_quote"><div dir="ltr">On Thu, Jul 21, 2016 at 7:45 AM Hans Wennborg <<a href="mailto:hans@chromium.org">hans@chromium.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I've reverted in r276186 as the bots have been unhappy for too long.<br>
<br>
On Wed, Jul 20, 2016 at 1:21 PM, Kostya Serebryany via llvm-commits<br>
<<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br>
> Bots are unhappy...<br>
><br>
> [ 88%] Building CXX object<br>
> lib/xray/CMakeFiles/clang_rt.xray-x86_64.dir/xray_flags.cc.o<br>
> /mnt/b/sanitizer-buildbot1/sanitizer-x86_64-linux/build/llvm/projects/compiler-rt/lib/xray/xray_init.cc:23:10:<br>
> fatal error: 'llvm/Support/ELF.h' file not found<br>
> #include "llvm/Support/ELF.h"<br>
>          ^<br>
><br>
><br>
> On Wed, Jul 20, 2016 at 7:14 AM, Dean Michael Berris via llvm-commits<br>
> <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br>
>><br>
>> Author: dberris<br>
>> Date: Wed Jul 20 09:14:50 2016<br>
>> New Revision: 276117<br>
>><br>
>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=276117&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=276117&view=rev</a><br>
>> Log:<br>
>> [compiler-rt] [XRay] Basic initialization and flag definition for XRay<br>
>> runtime<br>
>><br>
>> Summary:<br>
>> This patch implements the initialisation and patching routines for the<br>
>> XRay runtime, along with the necessary trampolines for function entry/exit<br>
>> handling. For now we only define the basic hooks for allowing an<br>
>> implementation to define a handler that gets run on function entry/exit. We<br>
>> expose a minimal API for controlling the behaviour of the runtime (patching,<br>
>> cleanup, and setting the handler to invoke when instrumenting).<br>
>><br>
>> Depends on D19904<br>
>><br>
>> Reviewers: echristo, kcc, rnk<br>
>><br>
>> Subscribers: rnk, mehdi_amini, llvm-commits<br>
>><br>
>> Differential Revision: <a href="https://reviews.llvm.org/D21612" rel="noreferrer" target="_blank">https://reviews.llvm.org/D21612</a><br>
>><br>
>> Added:<br>
>>     compiler-rt/trunk/include/xray/<br>
>>     compiler-rt/trunk/include/xray/xray_interface.h<br>
>>     compiler-rt/trunk/lib/xray/<br>
>>     compiler-rt/trunk/lib/xray/CMakeLists.txt<br>
>>     compiler-rt/trunk/lib/xray/xray_flags.cc<br>
>>     compiler-rt/trunk/lib/xray/xray_flags.h<br>
>>     compiler-rt/trunk/lib/xray/xray_flags.inc<br>
>>     compiler-rt/trunk/lib/xray/xray_init.cc<br>
>>     compiler-rt/trunk/lib/xray/xray_interface.cc<br>
>>     compiler-rt/trunk/lib/xray/xray_interface_internal.h<br>
>>     compiler-rt/trunk/lib/xray/xray_trampoline_x86.S<br>
>> Modified:<br>
>>     compiler-rt/trunk/CMakeLists.txt<br>
>>     compiler-rt/trunk/cmake/config-ix.cmake<br>
>>     compiler-rt/trunk/include/CMakeLists.txt<br>
>>     compiler-rt/trunk/lib/CMakeLists.txt<br>
>><br>
>> Modified: compiler-rt/trunk/CMakeLists.txt<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/CMakeLists.txt?rev=276117&r1=276116&r2=276117&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/CMakeLists.txt?rev=276117&r1=276116&r2=276117&view=diff</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/CMakeLists.txt (original)<br>
>> +++ compiler-rt/trunk/CMakeLists.txt Wed Jul 20 09:14:50 2016<br>
>> @@ -37,6 +37,8 @@ option(COMPILER_RT_BUILD_BUILTINS "Build<br>
>>  mark_as_advanced(COMPILER_RT_BUILD_BUILTINS)<br>
>>  option(COMPILER_RT_BUILD_SANITIZERS "Build sanitizers" ON)<br>
>>  mark_as_advanced(COMPILER_RT_BUILD_SANITIZERS)<br>
>> +option(COMPILER_RT_BUILD_XRAY "Build xray" ON)<br>
>> +mark_as_advanced(COMPILER_RT_BUILD_XRAY)<br>
>><br>
>>  if (COMPILER_RT_STANDALONE_BUILD)<br>
>>    if (NOT LLVM_CONFIG_PATH)<br>
>><br>
>> Modified: compiler-rt/trunk/cmake/config-ix.cmake<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/cmake/config-ix.cmake?rev=276117&r1=276116&r2=276117&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/cmake/config-ix.cmake?rev=276117&r1=276116&r2=276117&view=diff</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/cmake/config-ix.cmake (original)<br>
>> +++ compiler-rt/trunk/cmake/config-ix.cmake Wed Jul 20 09:14:50 2016<br>
>> @@ -161,6 +161,7 @@ set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86}<br>
>>  set(ALL_CFI_SUPPORTED_ARCH ${X86} ${X86_64} ${MIPS64})<br>
>>  set(ALL_ESAN_SUPPORTED_ARCH ${X86_64})<br>
>>  set(ALL_SCUDO_SUPPORTED_ARCH ${X86_64})<br>
>> +set(ALL_XRAY_SUPPORTED_ARCH ${X86_64})<br>
>><br>
>>  if(APPLE)<br>
>>    include(CompilerRTDarwinUtils)<br>
>> @@ -350,6 +351,9 @@ if(APPLE)<br>
>>    list_intersect(SCUDO_SUPPORTED_ARCH<br>
>>      ALL_SCUDO_SUPPORTED_ARCH<br>
>>      SANITIZER_COMMON_SUPPORTED_ARCH)<br>
>> +  list_intersect(XRAY_SUPPORTED_ARCH<br>
>> +    ALL_XRAY_SUPPORTED_ARCH<br>
>> +    SANITIZER_COMMON_SUPPORTED_ARCH)<br>
>>  else()<br>
>>    # Architectures supported by compiler-rt libraries.<br>
>>    filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH<br>
>> @@ -373,6 +377,7 @@ else()<br>
>>    filter_available_targets(ESAN_SUPPORTED_ARCH<br>
>> ${ALL_ESAN_SUPPORTED_ARCH})<br>
>>    filter_available_targets(SCUDO_SUPPORTED_ARCH<br>
>>      ${ALL_SCUDO_SUPPORTED_ARCH})<br>
>> +  filter_available_targets(XRAY_SUPPORTED_ARCH<br>
>> ${ALL_XRAY_SUPPORTED_ARCH})<br>
>>  endif()<br>
>><br>
>>  if (MSVC)<br>
>><br>
>> Modified: compiler-rt/trunk/include/CMakeLists.txt<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/CMakeLists.txt?rev=276117&r1=276116&r2=276117&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/CMakeLists.txt?rev=276117&r1=276116&r2=276117&view=diff</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/include/CMakeLists.txt (original)<br>
>> +++ compiler-rt/trunk/include/CMakeLists.txt Wed Jul 20 09:14:50 2016<br>
>> @@ -10,11 +10,18 @@ set(SANITIZER_HEADERS<br>
>>    sanitizer/msan_interface.h<br>
>>    sanitizer/tsan_interface_atomic.h)<br>
>><br>
>> +set(XRAY_HEADERS<br>
>> +  xray/xray_interface.h)<br>
>> +<br>
>> +set(COMPILER_RT_HEADERS<br>
>> +  ${SANITIZER_HEADERS}<br>
>> +       ${XRAY_HEADERS})<br>
>> +<br>
>>  set(output_dir ${COMPILER_RT_OUTPUT_DIR}/include)<br>
>><br>
>>  # Copy compiler-rt headers to the build tree.<br>
>>  set(out_files)<br>
>> -foreach( f ${SANITIZER_HEADERS} )<br>
>> +foreach( f ${COMPILER_RT_HEADERS} )<br>
>>    set( src ${CMAKE_CURRENT_SOURCE_DIR}/${f} )<br>
>>    set( dst ${output_dir}/${f} )<br>
>>    add_custom_command(OUTPUT ${dst}<br>
>> @@ -32,3 +39,7 @@ set_target_properties(compiler-rt-header<br>
>>  install(FILES ${SANITIZER_HEADERS}<br>
>>    PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ<br>
>>    DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/sanitizer)<br>
>> +# Install xray headers.<br>
>> +install(FILES ${XRAY_HEADERS}<br>
>> +  PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ<br>
>> +  DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/xray)<br>
>><br>
>> Added: compiler-rt/trunk/include/xray/xray_interface.h<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/xray/xray_interface.h?rev=276117&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/xray/xray_interface.h?rev=276117&view=auto</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/include/xray/xray_interface.h (added)<br>
>> +++ compiler-rt/trunk/include/xray/xray_interface.h Wed Jul 20 09:14:50<br>
>> 2016<br>
>> @@ -0,0 +1,66 @@<br>
>> +//===-- xray_interface.h ----------------------------------------*- C++<br>
>> -*-===//<br>
>> +//<br>
>> +//                     The LLVM Compiler Infrastructure<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// This file is a part of XRay, a dynamic runtime instrumentation system.<br>
>> +//<br>
>> +// APIs for controlling XRay functionality explicitly.<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +#ifndef XRAY_XRAY_INTERFACE_H<br>
>> +#define XRAY_XRAY_INTERFACE_H<br>
>> +<br>
>> +#include <cstdint><br>
>> +<br>
>> +extern "C" {<br>
>> +<br>
>> +enum XRayEntryType { ENTRY = 0, EXIT = 1 };<br>
>> +<br>
>> +// Provide a function to invoke for when instrumentation points are hit.<br>
>> This is<br>
>> +// a user-visible control surface that overrides the default<br>
>> implementation. The<br>
>> +// function provided should take the following arguments:<br>
>> +//<br>
>> +//   - function id: an identifier that indicates the id of a function;<br>
>> this id<br>
>> +//                  is generated by xray; the mapping between the<br>
>> function id<br>
>> +//                  and the actual function pointer is available through<br>
>> +//                  __xray_table.<br>
>> +//   - entry type: identifies what kind of instrumentation point was<br>
>> encountered<br>
>> +//                 (function entry, function exit, etc.). See the enum<br>
>> +//                 XRayEntryType for more details.<br>
>> +//<br>
>> +// Returns 1 on success, 0 on error.<br>
>> +extern int __xray_set_handler(void (*entry)(int32_t, XRayEntryType));<br>
>> +<br>
>> +// This removes whatever the currently provided handler is. Returns 1 on<br>
>> +// success, 0 on error.<br>
>> +extern int __xray_remove_handler();<br>
>> +<br>
>> +enum XRayPatchingStatus {<br>
>> +  NOT_INITIALIZED = 0,<br>
>> +  NOTIFIED = 1,<br>
>> +  ONGOING = 2,<br>
>> +  FAILED = 3<br>
>> +};<br>
>> +<br>
>> +// This tells XRay to patch the instrumentation points. This is an<br>
>> asynchronous<br>
>> +// process, and returns the following status in specific cases:<br>
>> +//<br>
>> +//   - 0 : XRay is not initialized.<br>
>> +//   - 1 : We've done the notification.<br>
>> +//   - 2 : Patching / un-patching is on-going.<br>
>> +extern XRayPatchingStatus __xray_patch();<br>
>> +<br>
>> +// Reverses the effect of __xray_patch(). This is an asynchronous<br>
>> process, and<br>
>> +// returns the following status in specific cases.<br>
>> +//<br>
>> +//   - 0 : XRay is not initialized.<br>
>> +//   - 1 : We've done the notification.<br>
>> +//   - 2 : Patching / un-patching is on-going.<br>
>> +extern int __xray_unpatch();<br>
>> +}<br>
>> +<br>
>> +#endif<br>
>><br>
>> Modified: compiler-rt/trunk/lib/CMakeLists.txt<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/CMakeLists.txt?rev=276117&r1=276116&r2=276117&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/CMakeLists.txt?rev=276117&r1=276116&r2=276117&view=diff</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/lib/CMakeLists.txt (original)<br>
>> +++ compiler-rt/trunk/lib/CMakeLists.txt Wed Jul 20 09:14:50 2016<br>
>> @@ -57,3 +57,7 @@ if(COMPILER_RT_BUILD_SANITIZERS)<br>
>>      add_subdirectory(scudo)<br>
>>    endif()<br>
>>  endif()<br>
>> +<br>
>> +if(COMPILER_RT_BUILD_XRAY)<br>
>> +  add_subdirectory(xray)<br>
>> +endif()<br>
>><br>
>> Added: compiler-rt/trunk/lib/xray/CMakeLists.txt<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/CMakeLists.txt?rev=276117&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/CMakeLists.txt?rev=276117&view=auto</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/lib/xray/CMakeLists.txt (added)<br>
>> +++ compiler-rt/trunk/lib/xray/CMakeLists.txt Wed Jul 20 09:14:50 2016<br>
>> @@ -0,0 +1,47 @@<br>
>> +# Build for the XRay runtime support library.<br>
>> +<br>
>> +set(XRAY_SOURCES<br>
>> +  xray_init.cc<br>
>> +       xray_interface.cc<br>
>> +       xray_flags.cc<br>
>> +)<br>
>> +<br>
>> +set(x86_64_SOURCES<br>
>> +               xray_trampoline_x86.S<br>
>> +               ${XRAY_SOURCES})<br>
>> +<br>
>> +include_directories(..)<br>
>> +include_directories(../../include)<br>
>> +<br>
>> +set(XRAY_CFLAGS ${SANITIZER_COMMON_CFLAGS})<br>
>> +<br>
>> +set(XRAY_COMMON_DEFINITIONS XRAY_HAS_EXCEPTIONS=1)<br>
>> +<br>
>> +add_compiler_rt_object_libraries(RTXray<br>
>> +               ARCHS ${XRAY_SUPPORTED_ARCH}<br>
>> +               SOURCES ${XRAY_SOURCES} CFLAGS ${XRAY_CFLAGS}<br>
>> +               DEFS ${XRAY_COMMON_DEFINITIONS})<br>
>> +<br>
>> +add_custom_target(xray)<br>
>> +set(XRAY_COMMON_RUNTIME_OBJECT_LIBS<br>
>> +               RTSanitizerCommon<br>
>> +               RTSanitizerCommonLibc)<br>
>> +<br>
>> +foreach (arch ${XRAY_SUPPORTED_ARCH})<br>
>> +               if (CAN_TARGET_${arch})<br>
>> +                               add_compiler_rt_runtime(clang_rt.xray<br>
>> +                                               STATIC<br>
>> +                                               ARCHS ${arch}<br>
>> +                                               SOURCES ${${arch}_SOURCES}<br>
>> +                                               CFLAGS ${XRAY_CFLAGS}<br>
>> +                                               DEFS<br>
>> ${XRAY_COMMON_DEFINITIONS}<br>
>> +                                               OBJECT_LIBS<br>
>> ${XRAY_COMMON_RUNTIME_OBJECT_LIBS}<br>
>> +                                               PARENT_TARGET xray)<br>
>> +               endif ()<br>
>> +endforeach()<br>
>> +<br>
>> +add_dependencies(compiler-rt xray)<br>
>> +<br>
>> +# if(COMPILER_RT_INCLUDE_TESTS)<br>
>> +#   add_subdirectory(tests)<br>
>> +# endif()<br>
>><br>
>> Added: compiler-rt/trunk/lib/xray/xray_flags.cc<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.cc?rev=276117&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.cc?rev=276117&view=auto</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/lib/xray/xray_flags.cc (added)<br>
>> +++ compiler-rt/trunk/lib/xray/xray_flags.cc Wed Jul 20 09:14:50 2016<br>
>> @@ -0,0 +1,61 @@<br>
>> +//===-- xray_flags.cc -------------------------------------------*- C++<br>
>> -*-===//<br>
>> +//<br>
>> +//                     The LLVM Compiler Infrastructure<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// This file is a part of XRay, a dynamic runtime instrumentation system.<br>
>> +//<br>
>> +// XRay flag parsing logic.<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +<br>
>> +#include "xray_flags.h"<br>
>> +#include "sanitizer_common/sanitizer_common.h"<br>
>> +#include "sanitizer_common/sanitizer_flag_parser.h"<br>
>> +#include "sanitizer_common/sanitizer_libc.h"<br>
>> +<br>
>> +using namespace __sanitizer;<br>
>> +<br>
>> +namespace __xray {<br>
>> +<br>
>> +Flags xray_flags_dont_use_directly; // use via flags().<br>
>> +<br>
>> +void Flags::SetDefaults() {<br>
>> +#define XRAY_FLAG(Type, Name, DefaultValue, Description) Name =<br>
>> DefaultValue;<br>
>> +#include "xray_flags.inc"<br>
>> +#undef XRAY_FLAG<br>
>> +}<br>
>> +<br>
>> +static void RegisterXRayFlags(FlagParser *P, Flags *F) {<br>
>> +#define XRAY_FLAG(Type, Name, DefaultValue, Description)<br>
>> \<br>
>> +  RegisterFlag(P, #Name, Description, &F->Name);<br>
>> +#include "xray_flags.inc"<br>
>> +#undef XRAY_FLAG<br>
>> +}<br>
>> +<br>
>> +void InitializeFlags() {<br>
>> +  SetCommonFlagsDefaults();<br>
>> +  auto *F = flags();<br>
>> +  F->SetDefaults();<br>
>> +<br>
>> +  FlagParser XRayParser;<br>
>> +  RegisterXRayFlags(&XRayParser, F);<br>
>> +  RegisterCommonFlags(&XRayParser);<br>
>> +<br>
>> +  // Override from command line.<br>
>> +  XRayParser.ParseString(GetEnv("XRAY_OPTIONS"));<br>
>> +<br>
>> +  InitializeCommonFlags();<br>
>> +<br>
>> +  if (Verbosity())<br>
>> +    ReportUnrecognizedFlags();<br>
>> +<br>
>> +  if (common_flags()->help) {<br>
>> +    XRayParser.PrintFlagDescriptions();<br>
>> +  }<br>
>> +}<br>
>> +<br>
>> +} // namespace __xray<br>
>><br>
>> Added: compiler-rt/trunk/lib/xray/xray_flags.h<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.h?rev=276117&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.h?rev=276117&view=auto</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/lib/xray/xray_flags.h (added)<br>
>> +++ compiler-rt/trunk/lib/xray/xray_flags.h Wed Jul 20 09:14:50 2016<br>
>> @@ -0,0 +1,37 @@<br>
>> +//===-- xray_flags.h -------------------------------------------*- C++<br>
>> -*-===//<br>
>> +//<br>
>> +//                     The LLVM Compiler Infrastructure<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// This file is a part of XRay, a dynamic runtime instruementation<br>
>> system.<br>
>> +//<br>
>> +// XRay runtime flags.<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +<br>
>> +#ifndef XRAY_FLAGS_H<br>
>> +#define XRAY_FLAGS_H<br>
>> +<br>
>> +#include "sanitizer_common/sanitizer_flag_parser.h"<br>
>> +<br>
>> +namespace __xray {<br>
>> +<br>
>> +struct Flags {<br>
>> +#define XRAY_FLAG(Type, Name, DefaultValue, Description) Type Name;<br>
>> +#include "xray_flags.inc"<br>
>> +#undef XRAY_FLAG<br>
>> +<br>
>> +  void SetDefaults();<br>
>> +};<br>
>> +<br>
>> +extern Flags xray_flags_dont_use_directly;<br>
>> +inline Flags *flags() { return &xray_flags_dont_use_directly; }<br>
>> +<br>
>> +void InitializeFlags();<br>
>> +<br>
>> +} // namespace __xray<br>
>> +<br>
>> +#endif // XRAY_FLAGS_H<br>
>><br>
>> Added: compiler-rt/trunk/lib/xray/xray_flags.inc<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.inc?rev=276117&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_flags.inc?rev=276117&view=auto</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/lib/xray/xray_flags.inc (added)<br>
>> +++ compiler-rt/trunk/lib/xray/xray_flags.inc Wed Jul 20 09:14:50 2016<br>
>> @@ -0,0 +1,18 @@<br>
>> +//===-- xray_flags.inc ------------------------------------------*- C++<br>
>> -*-===//<br>
>> +//<br>
>> +//                     The LLVM Compiler Infrastructure<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// XRay runtime flags.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +#ifndef XRAY_FLAG<br>
>> +#error "Define XRAY_FLAG prior to including this file!"<br>
>> +#endif<br>
>> +<br>
>> +XRAY_FLAG(bool, patch_premain, true,<br>
>> +          "Whether to patch instrumentation points before main.")<br>
>><br>
>> Added: compiler-rt/trunk/lib/xray/xray_init.cc<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_init.cc?rev=276117&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_init.cc?rev=276117&view=auto</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/lib/xray/xray_init.cc (added)<br>
>> +++ compiler-rt/trunk/lib/xray/xray_init.cc Wed Jul 20 09:14:50 2016<br>
>> @@ -0,0 +1,68 @@<br>
>> +//===-- xray_init.cc --------------------------------------------*- C++<br>
>> -*-===//<br>
>> +//<br>
>> +//                     The LLVM Compiler Infrastructure<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// This file is a part of XRay, a dynamic runtime instrumentation system.<br>
>> +//<br>
>> +// XRay initialisation logic.<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +<br>
>> +#include <atomic><br>
>> +#include <fcntl.h><br>
>> +#include <strings.h><br>
>> +#include <unistd.h><br>
>> +<br>
>> +#include "sanitizer_common/sanitizer_common.h"<br>
>> +#include "xray_flags.h"<br>
>> +#include "xray_interface_internal.h"<br>
>> +#include "llvm/Support/ELF.h"<br>
>> +<br>
>> +extern "C" {<br>
>> +extern void __xray_init();<br>
>> +extern const XRaySledEntry __start_xray_instr_map[]<br>
>> __attribute__((weak));<br>
>> +extern const XRaySledEntry __stop_xray_instr_map[] __attribute__((weak));<br>
>> +}<br>
>> +<br>
>> +using namespace __xray;<br>
>> +<br>
>> +// We initialize some global variables that pertain to specific sections<br>
>> of XRay<br>
>> +// data structures in the binary. We do this for the current process<br>
>> using<br>
>> +// /proc/curproc/map and make sure that we're able to get it. We signal<br>
>> failure<br>
>> +// via a global atomic boolean to indicate whether we've initialized<br>
>> properly.<br>
>> +//<br>
>> +std::atomic<bool> XRayInitialized{false};<br>
>> +<br>
>> +// This should always be updated before XRayInitialized is updated.<br>
>> +std::atomic<__xray::XRaySledMap> XRayInstrMap{};<br>
>> +<br>
>> +// __xray_init() will do the actual loading of the current process'<br>
>> memory map<br>
>> +// and then proceed to look for the .xray_instr_map section/segment.<br>
>> +void __xray_init() {<br>
>> +  InitializeFlags();<br>
>> +  if (__start_xray_instr_map == nullptr) {<br>
>> +    Report("XRay instrumentation map missing. Not initializing XRay.\n");<br>
>> +    return;<br>
>> +  }<br>
>> +<br>
>> +  // Now initialize the XRayInstrMap global struct with the address of<br>
>> the<br>
>> +  // entries, reinterpreted as an array of XRaySledEntry objects. We use<br>
>> the<br>
>> +  // virtual pointer we have from the section to provide us the correct<br>
>> +  // information.<br>
>> +  __xray::XRaySledMap SledMap{};<br>
>> +  SledMap.Sleds = __start_xray_instr_map;<br>
>> +  SledMap.Entries = __stop_xray_instr_map - __start_xray_instr_map;<br>
>> +  XRayInstrMap.store(SledMap, std::memory_order_release);<br>
>> +  XRayInitialized.store(true, std::memory_order_release);<br>
>> +<br>
>> +  // FIXME: Check the flag/environment before patching.<br>
>> +  if (flags()->patch_premain)<br>
>> +    __xray_patch();<br>
>> +}<br>
>> +<br>
>> +__attribute__((section(".preinit_array"),<br>
>> +               used)) void (*__local_xray_preinit)(void) = __xray_init;<br>
>><br>
>> Added: compiler-rt/trunk/lib/xray/xray_interface.cc<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface.cc?rev=276117&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface.cc?rev=276117&view=auto</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/lib/xray/xray_interface.cc (added)<br>
>> +++ compiler-rt/trunk/lib/xray/xray_interface.cc Wed Jul 20 09:14:50 2016<br>
>> @@ -0,0 +1,179 @@<br>
>> +//===-- xray_interface.cpp --------------------------------------*- C++<br>
>> -*-===//<br>
>> +//<br>
>> +//                     The LLVM Compiler Infrastructure<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// This file is a part of XRay, a dynamic runtime instrumentation system.<br>
>> +//<br>
>> +// Implementation of the API functions.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +<br>
>> +#include "xray_interface_internal.h"<br>
>> +#include <atomic><br>
>> +#include <cstdint><br>
>> +#include <cstdio><br>
>> +#include <errno.h><br>
>> +#include <limits><br>
>> +#include <sys/mman.h><br>
>> +<br>
>> +namespace __xray {<br>
>> +<br>
>> +// This is the function to call when we encounter the entry or exit<br>
>> sleds.<br>
>> +std::atomic<void (*)(int32_t, XRayEntryType)><br>
>> XRayPatchedFunction{nullptr};<br>
>> +<br>
>> +} // namespace __xray<br>
>> +<br>
>> +extern "C" {<br>
>> +// The following functions have to be defined in assembler, on a<br>
>> per-platform<br>
>> +// basis. See xray_trampoline_*.s files for implementations.<br>
>> +extern void __xray_FunctionEntry();<br>
>> +extern void __xray_FunctionExit();<br>
>> +}<br>
>> +<br>
>> +extern std::atomic<bool> XRayInitialized;<br>
>> +extern std::atomic<__xray::XRaySledMap> XRayInstrMap;<br>
>> +<br>
>> +int __xray_set_handler(void (*entry)(int32_t, XRayEntryType)) {<br>
>> +  if (XRayInitialized.load(std::memory_order_acquire)) {<br>
>> +    __xray::XRayPatchedFunction.store(entry, std::memory_order_release);<br>
>> +    return 1;<br>
>> +  }<br>
>> +  return 0;<br>
>> +}<br>
>> +<br>
>> +std::atomic<bool> XRayPatching{false};<br>
>> +<br>
>> +XRayPatchingStatus __xray_patch() {<br>
>> +  // FIXME: Make this happen asynchronously. For now just do this<br>
>> sequentially.<br>
>> +  if (!XRayInitialized.load(std::memory_order_acquire))<br>
>> +    return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized.<br>
>> +<br>
>> +  static bool NotPatching = false;<br>
>> +  if (!XRayPatching.compare_exchange_strong(NotPatching, true,<br>
>> +                                            std::memory_order_acq_rel,<br>
>> +                                            std::memory_order_acquire)) {<br>
>> +    return XRayPatchingStatus::ONGOING; // Already patching.<br>
>> +  }<br>
>> +<br>
>> +  // Step 1: Compute the function id, as a unique identifier per function<br>
>> in the<br>
>> +  // instrumentation map.<br>
>> +  __xray::XRaySledMap InstrMap =<br>
>> XRayInstrMap.load(std::memory_order_acquire);<br>
>> +  if (InstrMap.Entries == 0)<br>
>> +    return XRayPatchingStatus::NOT_INITIALIZED;<br>
>> +<br>
>> +  int32_t FuncId = 1;<br>
>> +  static constexpr uint8_t CallOpCode = 0xe8;<br>
>> +  static constexpr uint16_t MovR10Seq = 0xba41;<br>
>> +  static constexpr uint8_t JmpOpCode = 0xe9;<br>
>> +  uint64_t CurFun = 0;<br>
>> +  for (std::size_t I = 0; I < InstrMap.Entries; I++) {<br>
>> +    auto Sled = InstrMap.Sleds[I];<br>
>> +    auto F = Sled.Function;<br>
>> +    if (CurFun == 0)<br>
>> +      CurFun = F;<br>
>> +    if (F != CurFun) {<br>
>> +      ++FuncId;<br>
>> +      CurFun = F;<br>
>> +    }<br>
>> +<br>
>> +    // While we're here, we should patch the nop sled. To do that we<br>
>> mprotect<br>
>> +    // the page containing the function to be writeable.<br>
>> +    void *PageAlignedAddr =<br>
>> +        reinterpret_cast<void *>(Sled.Address & ~((2 << 16) - 1));<br>
>> +    std::size_t MProtectLen =<br>
>> +        (Sled.Address + 12) -<br>
>> reinterpret_cast<uint64_t>(PageAlignedAddr);<br>
>> +    if (mprotect(PageAlignedAddr, MProtectLen,<br>
>> +                 PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {<br>
>> +      printf("Failed mprotect: %d\n", errno);<br>
>> +      return XRayPatchingStatus::FAILED;<br>
>> +    }<br>
>> +<br>
>> +    static constexpr int64_t<br>
>> MinOffset{std::numeric_limits<int32_t>::min()};<br>
>> +    static constexpr int64_t<br>
>> MaxOffset{std::numeric_limits<int32_t>::max()};<br>
>> +    if (Sled.Kind == XRayEntryType::ENTRY) {<br>
>> +      // Here we do the dance of replacing the following sled:<br>
>> +      //<br>
>> +      // xray_sled_n:<br>
>> +      //   jmp +9<br>
>> +      //   <9 byte nop><br>
>> +      //<br>
>> +      // With the following:<br>
>> +      //<br>
>> +      //   mov r10d, <function id><br>
>> +      //   call <relative 32bit offset to entry trampoline><br>
>> +      //<br>
>> +      // We need to do this in the following order:<br>
>> +      //<br>
>> +      // 1. Put the function id first, 2 bytes from the start of the sled<br>
>> (just<br>
>> +      // after the 2-byte jmp instruction).<br>
>> +      // 2. Put the call opcode 6 bytes from the start of the sled.<br>
>> +      // 3. Put the relative offset 7 bytes from the start of the sled.<br>
>> +      // 4. Do an atomic write over the jmp instruction for the "mov<br>
>> r10d"<br>
>> +      // opcode and first operand.<br>
>> +      //<br>
>> +      // Prerequisite is to compute the relative offset to the<br>
>> +      // __xray_FunctionEntry function's address.<br>
>> +      int64_t TrampolineOffset =<br>
>> +          reinterpret_cast<int64_t>(__xray_FunctionEntry) -<br>
>> +          (static_cast<int64_t>(Sled.Address) + 11);<br>
>> +      if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) {<br>
>> +        // FIXME: Print out an error here.<br>
>> +        continue;<br>
>> +      }<br>
>> +      *reinterpret_cast<uint32_t *>(Sled.Address + 2) = FuncId;<br>
>> +      *reinterpret_cast<uint8_t *>(Sled.Address + 6) = CallOpCode;<br>
>> +      *reinterpret_cast<uint32_t *>(Sled.Address + 7) = TrampolineOffset;<br>
>> +      std::atomic_store_explicit(<br>
>> +          reinterpret_cast<std::atomic<uint16_t> *>(Sled.Address),<br>
>> MovR10Seq,<br>
>> +          std::memory_order_release);<br>
>> +    }<br>
>> +<br>
>> +    if (Sled.Kind == XRayEntryType::EXIT) {<br>
>> +      // Here we do the dance of replacing the following sled:<br>
>> +      //<br>
>> +      // xray_sled_n:<br>
>> +      //   ret<br>
>> +      //   <10 byte nop><br>
>> +      //<br>
>> +      // With the following:<br>
>> +      //<br>
>> +      //   mov r10d, <function id><br>
>> +      //   jmp <relative 32bit offset to exit trampoline><br>
>> +      //<br>
>> +      // 1. Put the function id first, 2 bytes from the start of the sled<br>
>> (just<br>
>> +      // after the 1-byte ret instruction).<br>
>> +      // 2. Put the jmp opcode 6 bytes from the start of the sled.<br>
>> +      // 3. Put the relative offset 7 bytes from the start of the sled.<br>
>> +      // 4. Do an atomic write over the jmp instruction for the "mov<br>
>> r10d"<br>
>> +      // opcode and first operand.<br>
>> +      //<br>
>> +      // Prerequisite is to compute the relative offset fo the<br>
>> +      // __xray_FunctionExit function's address.<br>
>> +      int64_t TrampolineOffset =<br>
>> +          reinterpret_cast<int64_t>(__xray_FunctionExit) -<br>
>> +          (static_cast<int64_t>(Sled.Address) + 11);<br>
>> +      if (TrampolineOffset < MinOffset || TrampolineOffset > MaxOffset) {<br>
>> +        // FIXME: Print out an error here.<br>
>> +        continue;<br>
>> +      }<br>
>> +      *reinterpret_cast<uint32_t *>(Sled.Address + 2) = FuncId;<br>
>> +      *reinterpret_cast<uint8_t *>(Sled.Address + 6) = JmpOpCode;<br>
>> +      *reinterpret_cast<uint32_t *>(Sled.Address + 7) = TrampolineOffset;<br>
>> +      std::atomic_store_explicit(<br>
>> +          reinterpret_cast<std::atomic<uint16_t> *>(Sled.Address),<br>
>> MovR10Seq,<br>
>> +          std::memory_order_release);<br>
>> +    }<br>
>> +<br>
>> +    if (mprotect(PageAlignedAddr, MProtectLen, PROT_READ | PROT_EXEC) ==<br>
>> -1) {<br>
>> +      printf("Failed mprotect: %d\n", errno);<br>
>> +      return XRayPatchingStatus::FAILED;<br>
>> +    }<br>
>> +  }<br>
>> +  XRayPatching.store(false, std::memory_order_release);<br>
>> +  return XRayPatchingStatus::NOTIFIED;<br>
>> +}<br>
>><br>
>> Added: compiler-rt/trunk/lib/xray/xray_interface_internal.h<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface_internal.h?rev=276117&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_interface_internal.h?rev=276117&view=auto</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/lib/xray/xray_interface_internal.h (added)<br>
>> +++ compiler-rt/trunk/lib/xray/xray_interface_internal.h Wed Jul 20<br>
>> 09:14:50 2016<br>
>> @@ -0,0 +1,40 @@<br>
>> +//===-- xray_interface_internal.h -------------------------------*- C++<br>
>> -*-===//<br>
>> +//<br>
>> +//                     The LLVM Compiler Infrastructure<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// This file is a part of XRay, a dynamic runtime instrumentation system.<br>
>> +//<br>
>> +// Implementation of the API functions. See also<br>
>> include/xray/xray_interface.h.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +#ifndef XRAY_INTERFACE_INTERNAL_H<br>
>> +#define XRAY_INTERFACE_INTERNAL_H<br>
>> +<br>
>> +#include "xray/xray_interface.h"<br>
>> +#include <cstdint><br>
>> +<br>
>> +extern "C" {<br>
>> +<br>
>> +struct XRaySledEntry {<br>
>> +  uint64_t Address;<br>
>> +  uint64_t Function;<br>
>> +  unsigned char Kind;<br>
>> +  unsigned char AlwaysInstrument;<br>
>> +  unsigned char Padding[14]; // Need 32 bytes<br>
>> +};<br>
>> +}<br>
>> +<br>
>> +namespace __xray {<br>
>> +<br>
>> +struct XRaySledMap {<br>
>> +  const XRaySledEntry *Sleds;<br>
>> +  std::size_t Entries;<br>
>> +};<br>
>> +}<br>
>> +<br>
>> +#endif<br>
>><br>
>> Added: compiler-rt/trunk/lib/xray/xray_trampoline_x86.S<br>
>> URL:<br>
>> <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_trampoline_x86.S?rev=276117&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_trampoline_x86.S?rev=276117&view=auto</a><br>
>><br>
>> ==============================================================================<br>
>> --- compiler-rt/trunk/lib/xray/xray_trampoline_x86.S (added)<br>
>> +++ compiler-rt/trunk/lib/xray/xray_trampoline_x86.S Wed Jul 20 09:14:50<br>
>> 2016<br>
>> @@ -0,0 +1,93 @@<br>
>> +//===-- xray_trampoline_x86.s -----------------------------------*- ASM<br>
>> -*-===//<br>
>> +//<br>
>> +//                     The LLVM Compiler Infrastructure<br>
>> +//<br>
>> +// This file is distributed under the University of Illinois Open Source<br>
>> +// License. See LICENSE.TXT for details.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +//<br>
>> +// This file is a part of XRay, a dynamic runtime instrumentation system.<br>
>> +//<br>
>> +// This implements the X86-specific assembler for the trampolines.<br>
>> +//<br>
>><br>
>> +//===----------------------------------------------------------------------===//<br>
>> +<br>
>> +       .text<br>
>> +       .file "xray_trampoline_x86.S"<br>
>> +       .globl __xray_FunctionEntry<br>
>> +       .align 16, 0x90<br>
>> +       .type __xray_FunctionEntry,@function<br>
>> +<br>
>> +__xray_FunctionEntry:<br>
>> +  .cfi_startproc<br>
>> +  // Save caller provided registers before doing any actual work.<br>
>> +       pushq %rbp<br>
>> +       .cfi_def_cfa_offset 16<br>
>> +       subq $72, %rsp<br>
>> +       movq    %rdi, 64(%rsp)<br>
>> +       movq  %rax, 56(%rsp)<br>
>> +       movq  %rdx, 48(%rsp)<br>
>> +       movq    %rsi, 40(%rsp)<br>
>> +       movq    %rcx, 32(%rsp)<br>
>> +       movq    %r8, 24(%rsp)<br>
>> +       movq    %r9, 16(%rsp)<br>
>> +<br>
>> +       // de-mangled, that's __xray::XRayPatchedFunction, and we're doing<br>
>> an acquire<br>
>> +       // load (on x86 is a normal mov instruction).<br>
>> +       movq    _ZN6__xray19XRayPatchedFunctionE(%rip), %rax<br>
>> +       testq   %rax, %rax<br>
>> +       je      .Ltmp0<br>
>> +<br>
>> +       // assume that %r10d has the function id.<br>
>> +       movl    %r10d, %edi<br>
>> +       xor     %esi,%esi<br>
>> +       callq   *%rax<br>
>> +.Ltmp0:<br>
>> +  // restore the registers<br>
>> +       movq    64(%rsp), %rdi<br>
>> +       movq  56(%rsp), %rax<br>
>> +       movq  48(%rsp), %rdx<br>
>> +       movq    40(%rsp), %rsi<br>
>> +       movq    32(%rsp), %rcx<br>
>> +       movq    24(%rsp), %r8<br>
>> +       movq    16(%rsp), %r9<br>
>> +       addq    $72, %rsp<br>
>> +       popq    %rbp<br>
>> +       retq<br>
>> +.Ltmp1:<br>
>> +       .size __xray_FunctionEntry, .Ltmp1-__xray_FunctionEntry<br>
>> +       .cfi_endproc<br>
>> +<br>
>> +       .globl __xray_FunctionExit<br>
>> +       .align 16, 0x90<br>
>> +       .type __xray_FunctionExit,@function<br>
>> +__xray_FunctionExit:<br>
>> +       .cfi_startproc<br>
>> +       // Save the important registers first. Since we're assuming that<br>
>> this<br>
>> +       // function is only jumped into, we only preserve the registers<br>
>> for<br>
>> +       // returning.<br>
>> +       // FIXME: Figure out whether this is sufficient.<br>
>> +       pushq   %rbp<br>
>> +       .cfi_def_cfa_offset 16<br>
>> +       subq    $24, %rsp<br>
>> +       .cfi_def_cfa_offset 32<br>
>> +       movq    %rax, 16(%rsp)<br>
>> +       movq    %rdx, 8(%rsp)<br>
>> +       movq    _ZN6__xray19XRayPatchedFunctionE(%rip), %rax<br>
>> +       testq %rax,%rax<br>
>> +       je      .Ltmp2<br>
>> +<br>
>> +       movl    %r10d, %edi<br>
>> +       movl    $1, %esi<br>
>> +       callq   *%rax<br>
>> +.Ltmp2:<br>
>> +  // Restore the important registers.<br>
>> +       movq    16(%rsp), %rax<br>
>> +       movq    8(%rsp), %rdx<br>
>> +       addq    $24, %rsp<br>
>> +       popq    %rbp<br>
>> +       retq<br>
>> +.Ltmp3:<br>
>> +       .size __xray_FunctionExit, .Ltmp3-__xray_FunctionExit<br>
>> +       .cfi_endproc<br>
>><br>
>><br>
>> _______________________________________________<br>
>> llvm-commits mailing list<br>
>> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
><br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
><br>
</blockquote></div>