Skip to content

Commit 1233740

Browse files
authored
Merge pull request #261 from plasma-umass/macos_2026-02-fix
Fix macOS build: add missing header files
2 parents 4a13850 + b465f5c commit 1233740

File tree

6 files changed

+206
-2
lines changed

6 files changed

+206
-2
lines changed

libcoz/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ if(APPLE)
2323
macho_support.h
2424
mac_interpose.cpp
2525
mac_interpose.h
26+
elf_compat.h
2627
)
2728
endif()
2829

libcoz/elf_compat.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2015, Charlie Curtsinger and Emery Berger,
3+
* University of Massachusetts Amherst
4+
* This file is part of the Coz project. See LICENSE.md file at the top-level
5+
* directory of this distribution and at http://github.com/plasma-umass/coz.
6+
*/
7+
8+
#ifndef COZ_ELF_COMPAT_H
9+
#define COZ_ELF_COMPAT_H
10+
11+
/**
12+
* ELF compatibility definitions for macOS.
13+
*
14+
* On Linux, <elf.h> provides ELF format definitions. On macOS, these
15+
* types don't exist natively, so we provide minimal compatibility
16+
* definitions for the types used by coz.
17+
*/
18+
19+
#ifdef __APPLE__
20+
21+
#include <cstdint>
22+
23+
/**
24+
* ELF Note header structure.
25+
* Used to parse NOTE sections in ELF files.
26+
*/
27+
typedef struct {
28+
uint32_t n_namesz; // Length of the note's name
29+
uint32_t n_descsz; // Length of the note's descriptor
30+
uint32_t n_type; // Type of the note
31+
} Elf64_Nhdr;
32+
33+
/**
34+
* Note type for GNU build ID.
35+
* The build ID is a unique identifier for a particular build of a binary.
36+
*/
37+
#ifndef NT_GNU_BUILD_ID
38+
#define NT_GNU_BUILD_ID 3
39+
#endif
40+
41+
#endif // __APPLE__
42+
43+
#endif // COZ_ELF_COMPAT_H

libcoz/mac_interpose.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2015, Charlie Curtsinger and Emery Berger,
3+
* University of Massachusetts Amherst
4+
* This file is part of the Coz project. See LICENSE.md file at the top-level
5+
* directory of this distribution and at http://github.com/plasma-umass/coz.
6+
*/
7+
8+
#ifdef __APPLE__
9+
10+
#include "mac_interpose.h"
11+
12+
/**
13+
* macOS interposition support implementation.
14+
*
15+
* On macOS, coz uses DYLD_INSERT_LIBRARIES to inject the profiler library.
16+
* Function interposition is achieved through:
17+
*
18+
* 1. Symbol interposition: Functions defined in libcoz.cpp with the same
19+
* names as system functions (e.g., pthread_create, pthread_mutex_lock)
20+
* will override the system versions when the library is loaded.
21+
*
22+
* 2. DYLD interposition tuples: For more reliable interposition, the
23+
* __DATA,__interpose section can be used to explicitly specify
24+
* which functions to replace.
25+
*
26+
* Currently, coz relies on symbol interposition (method 1) which works
27+
* well with DYLD_INSERT_LIBRARIES. The interposition tuples (method 2)
28+
* are available via the INTERPOSE macro in mac_interpose.h if needed
29+
* for specific functions that don't interpose correctly.
30+
*
31+
* Note: On macOS, some functions may require explicit interposition
32+
* tuples due to two-level namespace lookup. If interposition issues
33+
* are encountered, add INTERPOSE entries here.
34+
*/
35+
36+
// Currently no explicit interposition tuples are needed.
37+
// The symbol-based interposition in libcoz.cpp handles the required
38+
// pthread and signal functions.
39+
40+
#endif // __APPLE__

libcoz/mac_interpose.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2015, Charlie Curtsinger and Emery Berger,
3+
* University of Massachusetts Amherst
4+
* This file is part of the Coz project. See LICENSE.md file at the top-level
5+
* directory of this distribution and at http://github.com/plasma-umass/coz.
6+
*/
7+
8+
#ifndef COZ_MAC_INTERPOSE_H
9+
#define COZ_MAC_INTERPOSE_H
10+
11+
#ifdef __APPLE__
12+
13+
/**
14+
* macOS DYLD interposition support.
15+
*
16+
* On macOS, function interposition is done via DYLD_INSERT_LIBRARIES.
17+
* This header provides macros for creating interposition tuples that
18+
* tell the dynamic linker which functions to replace.
19+
*
20+
* The interposition mechanism uses the __DATA,__interpose section.
21+
*/
22+
23+
/**
24+
* Structure used by dyld for interposition.
25+
* When placed in the __DATA,__interpose section, dyld will replace
26+
* calls to 'original' with calls to 'replacement'.
27+
*/
28+
typedef struct {
29+
const void* replacement;
30+
const void* original;
31+
} interpose_tuple_t;
32+
33+
/**
34+
* Macro to create an interposition entry.
35+
* Usage: INTERPOSE(my_function, original_function)
36+
*
37+
* This creates a static entry in the __DATA,__interpose section that
38+
* tells dyld to replace calls to 'original_function' with 'my_function'.
39+
*/
40+
#define INTERPOSE(replacement, original) \
41+
__attribute__((used, section("__DATA,__interpose"))) \
42+
static const interpose_tuple_t interpose_##original = { \
43+
(const void*)(unsigned long)&replacement, \
44+
(const void*)(unsigned long)&original \
45+
}
46+
47+
/**
48+
* Alternative macro using dyld_interposing_tuple from mach-o/dyld-interposing.h
49+
* if available. This is the official Apple mechanism.
50+
*/
51+
#ifdef DYLD_INTERPOSE
52+
#undef INTERPOSE
53+
#define INTERPOSE(replacement, original) DYLD_INTERPOSE(replacement, original)
54+
#endif
55+
56+
#endif // __APPLE__
57+
58+
#endif // COZ_MAC_INTERPOSE_H

libcoz/macho_support.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,8 @@ bool get_section_type(const char* sectname, dwarf::section_type* out) {
334334
else if(std::strcmp(suffix, "pubtypes") == 0) *out = dwarf::section_type::pubtypes;
335335
else if(std::strcmp(suffix, "ranges") == 0) *out = dwarf::section_type::ranges;
336336
else if(std::strcmp(suffix, "str") == 0) *out = dwarf::section_type::str;
337-
// Handle both full name and Mach-O truncated name (16 char limit)
338-
else if(std::strcmp(suffix, "str_offsets") == 0 || std::strcmp(suffix, "str_offs") == 0) *out = dwarf::section_type::str_offsets;
337+
// Note: str_offsets section is used in DWARF 5 but not all libelfin versions support it
338+
// Skip it for now - the essential sections for line info are present
339339
else if(std::strcmp(suffix, "types") == 0) *out = dwarf::section_type::types;
340340
else if(assign_line_str(out,
341341
suffix,

libcoz/macho_support.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2015, Charlie Curtsinger and Emery Berger,
3+
* University of Massachusetts Amherst
4+
* This file is part of the Coz project. See LICENSE.md file at the top-level
5+
* directory of this distribution and at http://github.com/plasma-umass/coz.
6+
*/
7+
8+
#ifndef COZ_MACHO_SUPPORT_H
9+
#define COZ_MACHO_SUPPORT_H
10+
11+
#ifdef __APPLE__
12+
13+
#include <memory>
14+
#include <string>
15+
16+
namespace dwarf {
17+
class loader;
18+
}
19+
20+
namespace macho_support {
21+
22+
/**
23+
* Find an existing .dSYM bundle for the given binary path.
24+
* Returns the path to the DWARF file inside the bundle, or empty string if not found.
25+
*/
26+
std::string find_dsym_bundle(const std::string& binary_path);
27+
28+
/**
29+
* Extract the basename from a path.
30+
*/
31+
std::string basename_for(const std::string& path);
32+
33+
/**
34+
* Create a temporary directory for generated dSYM bundles.
35+
* Returns the path to the created directory, or empty string on failure.
36+
*/
37+
std::string make_temp_dir();
38+
39+
/**
40+
* Run dsymutil to generate debug symbols for a binary.
41+
* Returns true on success, false on failure.
42+
*/
43+
bool run_dsymutil(const std::string& binary_path, const std::string& bundle_path);
44+
45+
/**
46+
* Generate a dSYM bundle for the given binary if one doesn't exist.
47+
* Returns the path to the DWARF file inside the bundle, or empty string on failure.
48+
*/
49+
std::string generate_dsym_bundle(const std::string& binary_path);
50+
51+
/**
52+
* Load DWARF debug information from a Mach-O binary.
53+
* This will check for an existing .dSYM bundle, generate one if needed,
54+
* and return a dwarf::loader for the debug information.
55+
*/
56+
std::shared_ptr<dwarf::loader> load_debug_info(const std::string& binary_path);
57+
58+
} // namespace macho_support
59+
60+
#endif // __APPLE__
61+
62+
#endif // COZ_MACHO_SUPPORT_H

0 commit comments

Comments
 (0)