Code Monkey home page Code Monkey logo

orc's Introduction

Build and Test

ORC

ORC is a tool for finding violations of C++'s One Definition Rule on the OSX toolchain.

ORC is a play on DWARF which is a play on ELF. ORC is an acronym; while the O stands for ODR, in a bout of irony the R and C represent multiple (possibly conflicting) words.

The One Definiton Rule

What is it?

There are many writeups about the One Definition Rule (ODR), including the C++ Standard itself. The gist of the rule is that if a symbol is defined in a program, it is only allowed to be defined once. Some symbols are granted an exception to this rule, and are allowed to be defined multiple times. However, those symbols must be defined by identical token sequences.

Note that some compiler settings can also affect token sequences - for example, RTTI being enabled or disabled may alter the definition of a symbol (in this case, a class' vtable.)

What is an ODR violation?

Any symbol that breaks the above rule is an ODR violation (ODRV). In some instances, the linker may catch the duplicate symbol definition and emit a warning or error. However, the Standard states a linker is not required to do so. Andy G describes it well:

for performance reasons, the C++ Standard dictates that if you violate the One Definition Rule with respect to templates, the behavior is simply undefined. Since the linker doesn't care, violations of this rule are silent. source

Non-template ODRVs are possible, and the linker may be equally silent about them, too.

Why are ODRVs bad?

An ODRV usually means you have a symbol whose binary layout differs depending on the compilation unit that built it. Because of the rule, however, when a linker encounters multiple definitions, it is free to pick any of them and use it as the binary layout for a symbol. When the picked layout doesn't match the internal binary layout of the symbol in a compilation unit, the behavior is undefined.

Oftentimes the debugger is useless in these scenarios. It, too, will be using a single definition of a symbol for the entire program, and when you try to debug an ODRV the debugger may give you bad data, or point to a location in a file that doesn't seem correct. In the end, the debugger will appear to be lying to you, yet silently offer no clues as to what the underlying issue is.

Why should you fix an ODR?

Like all bugs, ODRVs take time to fix, so why should you fix an ODR violation in tested (and presumably working) code?

  • It can be difficult to know if an ODRV is causing a crash. The impact of an ODRV sometimes isn’t local to the location of the ODRV code. Stack corruption is a common symptom of ODRVs, and that can happen later and far away from the actual incorrect code.
  • The code actually generated is dependent on the inputs to the linker. Changing the linker inputs can cause different behaviors. And linker input changes can be caused by intentional reordering by a programmer, the output of a project generator changing, or as a simple by-product of adding files to your project.

How ORC works

ORC is a tool that performs the following:

  • Reads in a set of object and archive files (including libraries and frameworks)
  • Scans the object files for DWARF debug data, registering every type used by the component being built.
  • Detects and reports inconsistencies that are classified as ODRVs

Barring a bug in the tool, ORC does not generate false positives. Anything it reports is an ODRV.

At this time, ORC does not detect all possible violations of the One Definition Rule. We hope to expand and improve on what it can catch over time. Until then, this means that while ORC is a valuable check, a clean scan does not guarantee a program is free of ODRVs.

ORC can find:

  • structures / classes that aren't the same size
  • members of structures / classes that aren't at the same location
  • mis-matched vtables

A note on vtables: ORC will detect virtual methods that are in different slots. (Which is a nastly sort of corrupt program.) At this point, it won't detect a class that has a virtual methods that are a "superset" of a ODR violating duplicate class.

The ORC project

In addition to the main ORC sources, we try to provide a bevy of example applications that contain ODRVs that the tool should catch.

ORC was originally conceived on macOS. While its current implementation is focused there, it does not have to be constrained to that toolchain.

Building ORC

ORC is managed by cmake, and is built using the typical build conventions of a CMake-managed project:

  1. clone the repository
  2. within the repository folder:
    1. mkdir build
    2. cd build
    3. cmake -GXcode ..
  3. Open the generated Xcode project, build, and you're all set.

There are a handful of sample applications that ORC is integrated into for the purposes of testing. Those can be selected via the targets popup in Xcode.

Enabling ORC Profiling (ORC Developers only)

ORC uses Tracy as its profiling tool of choice, and it is enabled by default. To disable Tracy, specify the cmake command line like so:

cmake .. -GXcode -DTRACY_ENABLE=OFF

The Tracy dependency is required even if profiling is disabled (it will be compiled out of the runtime.) Note this option is cached, so you must explicitly turn it OFF or ON. Re-running the command line invocation with the option missing will cause its previous value to be used.

Calling ORC

ORC can be called directly from the command line, or inserted into the tool chain in the linker step. The output is unchanged; it's simply a matter of convenience in your workflow.

Command Line

Linker arguments

This mode is useful if you have the linker command and its arguments, and want to search for ODRVs seperate from the actual build.

Config file (see below)

  • 'forward_to_linker' = false
  • 'standalone_mode' = false

You need the ld command line arguments from XCode. Build with Xcode, (if you can't link, ORC can't help), copy the link command, and paste it after the ORC invocation. Something like:

/path/to/orc /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -target ... Debug/lem_mac

(It's a huge command line, abbreviated here.)

ORC will execute, and log ODR violations to the console.

List of Library files

If you have a list of library files for ORC to process, it can do that as well.

Config file (see below)

  • 'forward_to_linker' = false
  • 'standalone_mode' = true

In this mode, simply pass a list of libary files to ORC to process.

Linker

Config file (see below)

  • 'forward_to_linker' = true
  • 'standalone_mode' = false

To use ORC within your Xcode build project, override the following variables with a fully-qualified path to the ORC scripts:

"LIBTOOL": "/absolute/path/to/orc",
"LDTOOL": "/absolute/path/to/orc",
"ALTERNATE_LINKER": "/absolute/path/to/orc",

With those settings in place, Xcode should use ORC as the tool for both libtool and ld phases of the project build. Because of the forward_to_linker setting, ORC will invoke the proper link tool to produce a binary file. Once that completes, ORC will start its scan.

Among other settings, ORC can be configured to exit or merely warn when an ODRV is detected.

Config file

ORC will walk the current directory up, looking for a config file named either:

  • .orc-config, or
  • _orc-config

If found, many switches can control ORC's logic. Please see the _orc_config in the repository for examples. ORC will prefer .orc-config so it's simple to copy the original _orc_config and change values locally in the .orc-config.

Output

For example:

error: ODRV (structure:byte_size); conflict in `object`
    compilation unit: a.o:
        definition location: /Volumes/src/orc/extras/struct0/src/a.cpp:3
        calling_convention: pass by value; 5 (0x5)
        name: object
        byte_size: 4 (0x4)
    compilation unit: main.o:
        definition location: /Volumes/src/orc/extras/struct0/src/main.cpp:3
        calling_convention: pass by value; 5 (0x5)
        name: object
        byte_size: 1 (0x1)

structure:byte_size is known as the ODRV category, and details exactly what kind of violation this error represents. The two compilation units that are in conflict are then output, along with the DWARF information that resulted in the collision.

struct object { ... }

In a.o: and In main.o are the 2 object files or archives that are mis-matched. The ODR is likely caused by mis-matched compile or #define settings in compiling these archives. byte_size is the actual value causing an error.

definition location: /Volumes/src/orc/extras/struct0/src/a.cpp:3

What line and file the object was declared in. So line 3 of a.cpp in this example.

Output Consistency

For the same version of ORC, and the same input, ORC will always write the same output. Where "the same" is byte identical and a diff tool will show no differences.

Achieving (and likely maintaining) consistent output is surprisingly challenging in a highly multi-threaded application.

Please keep in mind however that this does NOT apply to different versions of ORC. Changes to ORC will almost certainly result in output changes.

There is also no guarantee that a “small” change in the input files will guarantee a “small” change in the ORC output. This behavior is desirable and will likely be an area of future improvement.

The ORC Test App (orc_test)

A unit test application is provided to ensure that ORC is catching what is purports to catch. orc_test introduces a miniature "build system" to generate object files from known sources to produce known ODR violations. It then processes the object files using the same engine as the ORC command line tool, and compares the results against an expected ODRV report list.

The Test Battery Structure

Every unit test in the battery is discrete, and contains:

  1. A set of source files
  2. odrv_test.toml, a high level TOML file describing the parameters of the test

In general, a single test should elicit a single ODR violation, but this may not be possible in all cases.

The Source File(s)

These files are standard C++ source files. Their quantity and size should be very small - only big enough as needed to cause the intended ODRV.

The odrv_test.toml File

The settings file describes to the test application what source(s) need to be compiled, what compilation flags should be used for the test, and what ODRVs the system needs to be on the lookout as a result of linking the generated object file(s) together.

Specifying Sources

Test sources are specified with a [[source]] directive:

[[source]]
    path = "one.cpp"
    obj = "one"
    flags = [
        "-Dfoo=1"
    ]

The path field describes a path to the file relative to odrv_test.toml. It is the only required field.

The obj field specifies the name of the (temporary) object file to be created. If this name is omitted, a pseudo-random name will be used.

The flags field specifies compilation flags that will be used specifically for this compilation unit. Using this field, it is possible to reuse the same source file with different compilation flags to elicit an ODRV.

Specifying ODRVs

ODRVs are specified with the [[odrv]] directive:

[[odrv]]
    category = "subprogram:vtable_elem_location"
    linkage_name = "_ZNK6object3apiEv"

The category field describes the specific type of ODR violation the test app should expect to find.

The linkage_name field describes the specific symbol that caused the ODRV. It is currently unused, but will be enforced as the test app matures.

Fields In Development

The following flags are not currently in use or will undergo heavy changes as the unit test app continues to mature.

  • [compile_flags]: A series of compilation flags that should be applied to every source file in the unit test.

  • [orc_test_flags]: A series of runtime settings to pass to the test app for this test.

  • [orc_flags]: A series of runtime settings to pass to the ORC engine for this test.

orc's People

Contributors

bheath-adobe avatar fosterbrereton avatar hanickadot avatar leethomason avatar omnitroid avatar stilllman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

orc's Issues

UBSan failure doesn't cause the build to fail

Describe the bug

Lucky, really, since #49 is a legitimate UBSan error. But even though UBSan reports the error, the CI build on github still succeeds. Likely a problem with our build scripts.

Expected behavior

The build should fail.

Obviously we need to fix or exclude #49 first.

ORC Reporting <unsupported file index>

ORC reports are failing to include proper definition location attribution:

warning: ODRV (structure:byte_size); conflict in `ComponentInfo`
    within: xyz.a:
    within: xyz.o:
        definition location: <unsupported file index>:1194
        calling_convention: pass by reference; 4 (0x4)
        name: ComponentInfo
        byte_size: 8 (0x8)

    within: abc.a:
    within: abc.o:
        definition location: <unsupported file index>:750
        calling_convention: pass by reference; 4 (0x4)
        name: ComponentInfo
        byte_size: 192 (0xc0)

replace `std::partition` with `std::remove_if`

The latter's performance will be slightly better, as it doesn't concern itself with the values in the entries that are going to be removed.

I normally wouldn't file an issue for such a small thing, but it's happening in register_dies where every cycle counts, and didn't want to forget about it.

C++20 has std::erase_if which we could also use, assuming it's available.

@baheath pointed me to this article, wherein it describes unstable_remove_if, which is what I think I want.

Orc does not check the directory it is in for the config file

Describe the bug

The documentation states: "ORC will walk the current directory up, looking for a config file named either..". However, when a config file is placed in the same folder as the orc executable it does not find this config file. It does find it when placed in the parent directory, though.

Expected behavior

Given the formulation in the documentation, I would expect ORC to check the directory the executable is in first.

Environment:

  • OS: MacOS 10.15
  • Compiler/IDE: Ninja
  • Version: 0.0.1

Duplicate Output

Describe the bug

If logging is used, ORC outputs to multiple streams, which causes the number of ODRVs reported to be doubled.

info: ORC complete.
info:   537 ODRVs reported

becomes:

info: ORC complete.
info:   1074 ODRVs reported

Expected behavior

The problem is straightforward:
++globals::instance()._odrv_count; in std::ostream& operator<<(std::ostream& s, const odrv_report& report) is called twice when there is logging.

But the actual issue IMO is that we have filter logic and side effects in operator<<. operator<< should:

  • have no side effects
  • only output - not filter

Fixing this will take some moderate refactoring.

Catch typedef ODRVs

ORC right now assumes typedefs cannot contribute to ODRVs. This is because they do not create new types like other declarations do- they simply make it easier to utilize other type definitions. Because they do not introduce new types, they cannot cross a TU boundary, and therefore cannot contribute to an ODRV.

Except they can. When they're used to give a name to an anonymous class or struct, it turns out typedefs do introduce a new class name. Example:

In the first TU:

typedef struct {} S, S1;

and in the second TU:

typedef struct {int x;} S, S2;

More details in this excellent writeup on Stackoverflow.

Control output directory

Describe the bug

Quoting:
ORC has a config setting for the output filename.

However, ORC will create this file in the current working directory, which for metabuild projects ends up being the same root directory for all libraries, so the file just gets overwritten for each library that is linked. Instead, I would like ORC to process the -o or --output linker arg, and then write the output file to the same location. So if the linker is invoked with -o build/output/dir/my-lib/blah.a, it should write build/output/dir/my-lib/blah.a.orc_out.txt

(That behavioral change could also be a orc-config parameter if we want it to be backward compatible.)

Remove unused / outdated features

A number of older ORC features are no longer used, and/or have been broken by subsequent improvements to the tool (e.g., parallel die processing.)

Remove the following features from the tool, and any settings/globals/metrics associated with them:

  • print_symbol_paths
  • show_progress

JSON Output Mode

Add support for JSON-formatted reports. I spoke with @bheath-adobe and here's what we'll do:

  • Add a output_file_mode setting to orc_config whose two valid values are text and json, defaulting to text.
  • When set to json, the destination files for either the output_file or relative_output_file settings will contain only valid JSON.
  • The JSON-formatted report will still need to honor symbol_ignore, violation_report, and violation_ignore as reports do today.

On the implementation side, we should always generate the JSON data structure. The current path of filtering and reporting ODRVs, then, would happen over the JSON and not the current native data structures. This will ensure that as ORC's output and reporting evolves, so too will the JSON output.

Murmer3 implementation has UB flagged by UBSan (though probably safe on desktop)

Describe the bug

UBSan correctly flags this line in the Murmer3 code:

/Users/runner/work/orc/orc/src/hash.cpp:40:69: runtime error: load of misaligned address 0x00010c28f87b for type 'const uint64_t' (aka 'const unsigned long long'), which requires 8 byte alignment

This is correct. ORC string pools aren't aligned to any memory address (and const char* doesn't need to be), but Murmer3 casts a void* to a uint64_t* and that causes the UBSan flag.

Note I can't imagine any machine capable of running ORC that would actually fail on an unaligned read, but the UBSan flag is correct.

Expected behavior

The correct fix is probably in Murmer3 - it takes in a void* without restriction and should deal with alignment. That's not a trivial change.

We could move our strings to 16 byte alignment, but that wastes a bunch of memory.

ODRVs reported twice for different architectures

Describe the bug

An ODRV is being reported twice, once for each architecture.

warning: ODRV (class:byte_size); conflict in `adobe::cloudservices::platform::HttpRequestObject`
    within: liblecplatform.a:
    within: arch.arm64:
etc.
warning: ODRV (class:byte_size); conflict in `adobe::cloudservices::platform::HttpRequestObject`
    within: liblecplatform.a:
    within: arch.x86_64:
etc.

I'm not sure how we should handle this. (The only way to tell is the ancestry chain?) Recording here for discussion. It's interesting we only see one case of this - is there only one library file that has both architectures when we link?

Build fails on Ubuntu 20.04

Describe the bug

The build fails with errors in several files.

Expected behavior

Should be able to compile with cmake --build build.

Environment:

  • OS: Ubuntu 20.04
  • Compiler/IDE: Clang 12.0.1, GCC 9.3.0, Intel oneAPI 2021.3.0
  • Version: commit 223084c

Additional context

> CC=clang CXX=clang++ cmake ..
-- The C compiler identification is Clang 12.0.1
-- The CXX compiler identification is Clang 12.0.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- ORC third-party: creating target 'stlab::stlab'...
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Failed
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
CMake Warning (dev) at build/_deps/stlab-src/stlab/concurrency/CMakeLists.txt:1 (target_sources):
  Policy CMP0076 is not set: target_sources() command converts relative paths
  to absolute.  Run "cmake --help-policy CMP0076" for policy details.  Use
  the cmake_policy command to set the policy and suppress this warning.

  An interface source of target "stlab" has a relative path.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- stlab: Task System: header
-- ORC third-party: creating target 'tomlplusplus::tomlplusplus'...
-- ORC third-party: creating target 'TBB::tbb'...
CMake Warning (dev) at build/_deps/tbb-src/CMakeLists.txt:95 (option):
  Policy CMP0077 is not set: option() honors normal variables.  Run "cmake
  --help-policy CMP0077" for policy details.  Use the cmake_policy command to
  set the policy and suppress this warning.

  For compatibility with older versions of CMake, option is clearing the
  normal variable 'TBB_TEST'.
This warning is for project developers.  Use -Wno-dev to suppress it.

-- CMAKE_BUILD_TYPE is not specified. Using default: RelWithDebInfo
-- Check if compiler accepts -pthread
-- Check if compiler accepts -pthread - yes
-- Checking for one of the modules 'hwloc'
-- The tbbbind_2_0 target will be configured using the HWLOC 2.1.0
-- Configuring done
-- Generating done
-- Build files have been written to: $HOME/Projects/orc/build
> make 
[  0%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/address_waiter.cpp.o
[  1%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/allocator.cpp.o
[  1%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/arena.cpp.o
[  1%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/arena_slot.cpp.o
[  2%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/concurrent_bounded_queue.cpp.o
[  2%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/dynamic_link.cpp.o
[  2%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/exception.cpp.o
[  3%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/governor.cpp.o
[  3%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/global_control.cpp.o
[  3%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/itt_notify.cpp.o
[  3%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/main.cpp.o
[  4%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/market.cpp.o
[  4%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/misc.cpp.o
[  4%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/misc_ex.cpp.o
[  5%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/observer_proxy.cpp.o
[  5%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/parallel_pipeline.cpp.o
[  5%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/private_server.cpp.o
[  5%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/profiling.cpp.o
[  6%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/rml_tbb.cpp.o
[  6%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/rtm_mutex.cpp.o
[  6%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/rtm_rw_mutex.cpp.o
[  7%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/semaphore.cpp.o
[  7%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/small_object_pool.cpp.o
[  7%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/task.cpp.o
[  8%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/task_dispatcher.cpp.o
[  8%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/task_group_context.cpp.o
[  8%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/version.cpp.o
[  8%] Building CXX object _deps/tbb-build/src/tbb/CMakeFiles/tbb.dir/queuing_rw_mutex.cpp.o
[  9%] Linking CXX shared library ../../../../clang_12.0_cxx11_64_relwithdebinfo/libtbb.so
[  9%] Built target tbb
[  9%] Building CXX object CMakeFiles/orc_orc.dir/src/ar.cpp.o
In file included from $HOME/Projects/orc/src/ar.cpp:8:
In file included from $HOME/Projects/orc/include/orc/ar.hpp:13:
$HOME/Projects/orc/include/orc/parse_file.hpp:78:17: error: enumeration value '_S_ios_seekdir_end' not handled in switch [-Werror,-Wswitch]
        switch (dir) {
                ^
$HOME/Projects/orc/include/orc/parse_file.hpp:93:14: error: no member named 'memcpy' in namespace 'std'
        std::memcpy(p, _p, n);
        ~~~~~^
$HOME/Projects/orc/include/orc/parse_file.hpp:211:37: error: no template named 'function' in namespace 'std'
using register_dies_callback = std::function<void(dies)>;
                               ~~~~~^
$HOME/Projects/orc/include/orc/parse_file.hpp:212:31: error: no template named 'function' in namespace 'std'
using do_work_callback = std::function<void(std::function<void()>)>;
                         ~~~~~^
$HOME/Projects/orc/include/orc/parse_file.hpp:212:50: error: no member named 'function' in namespace 'std'
using do_work_callback = std::function<void(std::function<void()>)>;
                                            ~~~~~^
$HOME/Projects/orc/include/orc/parse_file.hpp:212:66: error: expected expression
using do_work_callback = std::function<void(std::function<void()>)>;
                                                                 ^
$HOME/Projects/orc/include/orc/parse_file.hpp:213:30: error: no template named 'function' in namespace 'std'
using empool_callback = std::function<pool_string(std::string_view)>;
                        ~~~~~^
$HOME/Projects/orc/include/orc/parse_file.hpp:216:5: error: unknown type name 'register_dies_callback'
    register_dies_callback _register_die;
    ^
$HOME/Projects/orc/include/orc/parse_file.hpp:217:5: error: unknown type name 'do_work_callback'
    do_work_callback _do_work;
    ^
$HOME/Projects/orc/include/orc/parse_file.hpp:218:5: error: unknown type name 'empool_callback'
    empool_callback _empool;
    ^
10 errors generated.
make[2]: *** [CMakeFiles/orc_orc.dir/build.make:76: CMakeFiles/orc_orc.dir/src/ar.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:665: CMakeFiles/orc_orc.dir/all] Error 2
make: *** [Makefile:156: all] Error 2

Wrap all sources in a namespace

To eat our own dogfood here, the sources should be wrapped in a namespace to minimize the chances of ODRVs happen. For source-level structures and algorithms, they should be wrapped in an anonymous namespace (I believe most - but maybe not all - already are.)

Better `debug_lines` support

DWARF4 states that the debug_lines section contains names of the files where symbols are defined. These are then referenced in decl_file attribute entries in debug_info by index into ORC's _decl_files table.

Right now, ORC just parses the beginning of debug_lines to get the initial set of decl_file entries, assuming that's all there are, and skips over the rest of the debug_lines section. However, there are some op codes in debug_lines that can add new entries to the decl_files table. ORC does not handle those, and so any ensuing decl_file with an index beyond the initial set of decl_file entries are dropped on the floor.

ORC should traverse the rest of the debug_lines data, looking for DW_LNE_define_file op codes, and append those files to the _decl_files table as they are found.

String Pooling

Describe the bug

ORC uses a lot of memory. One suggestion is to pool strings.

The interned string object:

  • never moves in memory
  • encodes the length, hash, and string data (probably just packed into uint8_t)
  • is guaranteed to be unique
    The reference to the interned string:
  • Is only the size of a pointer (which points to the string, but can access the size & hash)
  • Pointer equality is the same as string equality (they are unique)
  • string_view can be easily and efficiently generated when needed (the length and data is encoded in the interned data).
  • Reading a string is generally only 1-2 cache fetches
  • Reading doesn't require synchronization (they are unique)
    So "only" writing needs to be locked. That's still a big deal, mind you. But if we work out the threading performance, I think the interning is an optimal memory scheme without resorting to compression. (Ropes, tris, etc.) Strings are in coherent memory, packed, and unique. The instance of the string is always the size of a pointer.

ORC cannot identify static free functions

Describe the bug

static free functions that are not ODRVs can be reported as such by ORC. Example:

// in a.cpp
static auto foo() {
    return 42;
}

// in b.cpp
static auto foo() {
    return 84;
}

This is causing high_pc attribute checks to report false positives, as functions with the same name/linkage name are reported as conflicting, even though they're static free functions and therefore guaranteed not to conflict.

Expected behavior

Static free functions should not be reported as ODR violations.

Additional context

The only clue I've been able to find to discern the storage class specifier of a static function is in it's name mangling. For example:

I also just discovered that a static local routine will mangle differently.

static void my_foo() {}

will mangle to _ZL6my_foov, while:

void my_foo() {}

will mangle to _Z6my_foov. Note the L in the former case (presumably for ‘local’?)

See also the ABI specification on name mangling for more details.

Stops when processing system libraries

Describe the bug

Orc throws an errors on system libraries, and prints an error. For example:

 -framework AGL
 -framework AdbePM
 -framework AppKit

Expected behavior

They should be getting processed, and the paths filled in, by the processor.

Source/Object Files

target: lem_mac

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.