halide / Halide

a language for fast, portable data-parallel computation
https://halide-lang.org
Other
5.77k stars 1.07k forks source link

Introspection segfaults on golang executables #8263

Closed fredcadete closed 1 week ago

fredcadete commented 1 month ago

For the use case where a golang executable has a dynamic dependency on libHalide.so , introspection is throwing a segfault during dynamic linking.

Observed on:

  1. Halide 16.0.0 or main's current revision
  2. go 1.22.3
  3. Linux x64

A minimal reproduction is below. It involves a C++ wrapper to depend on Halide with a C API, and a go binary that uses cgo to depend on the wrapper.

libwrapper.cpp:

#include <Halide.h>
#include "libwrapper.h"

const char* running_program_name()
{
    return Halide::Internal::running_program_name().c_str();
}

libwrapper.h:

#ifdef __cplusplus
extern "C"
{
#endif

const char* running_program_name();

#ifdef __cplusplus
}
#endif

main.go:

package main

/*
#include "libwrapper.h"
*/
import "C"
import "os"

func main() {
    C.running_program_name()
    os.Exit(0)
}

Build steps: g++ libwrapper.cpp --std=c++17 -lHalide -fPIC -shared -o libwrapper.so CGO_LDFLAGS="-L. -lwrapper -lHalide" go build -o test_go main.go

Execution:

 ./test_go 
Segmentation fault

Backtrace from GDB:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff4019e45 in llvm::DataExtractor::getULEB128(unsigned long*, llvm::Error*) const () from /home/fcadete/contrib/Halide/dist/usr/local/lib/libHalide.so.16
(gdb) bt
#0  0x00007ffff4019e45 in llvm::DataExtractor::getULEB128(unsigned long*, llvm::Error*) const () from /home/fcadete/contrib/Halide/dist/usr/local/lib/libHalide.so.16
#1  0x00007ffff0eaa7b5 in Halide::Internal::Introspection::(anonymous namespace)::DebugSections::parse_debug_abbrev (this=0x569ef0, e=..., off=1267662848) at /workspace/src/Introspection.cpp:1010
#2  0x00007ffff0eab1e3 in Halide::Internal::Introspection::(anonymous namespace)::DebugSections::parse_debug_info (this=0x569ef0, e=..., debug_abbrev=..., debug_str=..., debug_line_str=..., debug_ranges=...) at /workspace/src/Introspection.cpp:1104
#3  0x00007ffff0eaa4dd in Halide::Internal::Introspection::(anonymous namespace)::DebugSections::parse_object_file (this=0x569ef0, obj=0x56a090) at /workspace/src/Introspection.cpp:991
#4  0x00007ffff0ea9bfc in Halide::Internal::Introspection::(anonymous namespace)::DebugSections::load_and_parse_object_file (this=0x569ef0, binary="/home/fcadete/contrib/Halide/test/go/test_go") at /workspace/src/Introspection.cpp:934
#5  0x00007ffff0ea5abf in Halide::Internal::Introspection::(anonymous namespace)::DebugSections::DebugSections (this=0x569ef0, binary="/home/fcadete/contrib/Halide/test/go/test_go") at /workspace/src/Introspection.cpp:211
#6  0x00007ffff0eb173c in Halide::Internal::Introspection::test_compilation_unit (test=0x7ffff08b15bc <HalideIntrospectionCanary::test(bool (*)(void const*, std::string const&))>, test_a=
    0x7ffff08b0ebf <HalideIntrospectionCanary::test_a(void const*, std::string const&)>, calib=0x7ffff08b0e9e <HalideIntrospectionCanary::offset_marker()>) at /workspace/src/Introspection.cpp:2339
#7  0x00007ffff08b17cc in HalideIntrospectionCanary::(anonymous namespace)::TestCompilationUnit::TestCompilationUnit (this=0x7ffff7d04802 <HalideIntrospectionCanary::test_object>) at /workspace/src/Introspection.h:144
#8  0x00007ffff08b4542 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /workspace/src/Introspection.h:149
#9  0x00007ffff08b455c in _GLOBAL__sub_I_AbstractGenerator.cpp(void) () at /workspace/src/AbstractGenerator.cpp:262
#10 0x00007ffff7fe0b9a in call_init (l=<optimized out>, argc=argc@entry=1, argv=argv@entry=0x7fffffffd228, env=env@entry=0x7fffffffd238) at dl-init.c:72
#11 0x00007ffff7fe0ca1 in call_init (env=0x7fffffffd238, argv=0x7fffffffd228, argc=1, l=<optimized out>) at dl-init.c:30
#12 _dl_init (main_map=0x7ffff7ffe190, argc=1, argv=0x7fffffffd228, env=0x7fffffffd238) at dl-init.c:119
#13 0x00007ffff7fd013a in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#14 0x0000000000000001 in ?? ()
#15 0x00007fffffffd5eb in ?? ()
#16 0x0000000000000000 in ?? ()

I was not able to identify the root cause, and worked around in a local build by deactivating introspection. Thank you for the useful library, and I hope the report is useful.

abadams commented 3 weeks ago

Sadly we don't have the bandwidth to fix introspection, right now, so ... #8273

zvookin commented 3 weeks ago

Per discussion in the dev meeting, I just perused the C++26 proposals and despite a fairly extensive introspection/reflection proposal, I don't see a way to get the name of a C++ variable being constructed into the constructor without providing it explicitly. C++23 does appear to have a library for stack traces:.