You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mac OS M1下PyBind11链接库时__DATA_CONST错误排查

问题:Mac M1环境下链接PyBind11模块时__DATA_CONST段权限错误

我开发了一款面向Mac OS的科学计算库,该库在Linux环境下可正常编译运行,但在Mac OS M1环境中,将其链接到PyBind11模块时出现如下错误:

ld: __DATA_CONST segment missing SG_READ_ONLY flag in '/Users/ec2-user/libdescriptor/bin/libdescriptor.dylib'

或

ld: __DATA_CONST segment permissions is not 'rw-' in '/Users/ec2-user/libdescriptor/bin/libdescriptor.dylib'

该库编译时使用LLVM 13及lld链接器(因需调用自定义LTO插件Enzyme进行函数微分),编译过程无报错。以下是相关构建文件及工具输出:

1. libdescriptor.dylib的Makefile

CXX := /opt/homebrew/Cellar/llvm@13/13.0.1_2/bin/clang++
CXXFLAGS := -std=c++17 -O3 -dynamiclib -fuse-ld=lld -flto  -Iinclude

#Enzyme lib location
ENZYME_LIB := /usr/local/lib/LLDEnzyme-13.dylib

# Directories
SRCDIR := src
INCDIR := include
OBJDIR := obj
BINDIR := bin

# Output library
TARGET := $(BINDIR)/libdescriptor.dylib

# Source files
SRCFILES := $(wildcard $(SRCDIR)/*.cpp) $(wildcard $(SRCDIR)/*/*.cpp)
# Object files
OBJFILES := $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SRCFILES))

# Create directories if they don't exist
$(shell mkdir -p $(BINDIR) $(OBJDIR) $(OBJDIR)/maths)

# Default target
all: $(TARGET)

# Link the executable
$(TARGET): $(OBJFILES)
    $(CXX)  -flto $(CXXFLAGS) -o $@ $^  -Wl,--lto-legacy-pass-manager -Wl,-mllvm -load=$(ENZYME_LIB) -Wl,-mllvm,-enzyme-loose-types 

# -Wl,-segprot,__DATA_CONST,r,r  <- modifications suggested by ChatGPT
#-Wl,-segprot,__DATA_CONST,ro,ro

# Compile source files into object files
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
    $(CXX) $(CXXFLAGS) -c $< -o $@

# Clean up build files
clean:
    rm -rf $(OBJDIR) $(BINDIR)

.PHONY: all clean

2. PyBind11模块的CMakefile

cmake_minimum_required(VERSION 3.16)

project(libdescriptor)

set(CMAKE_BUILD_TYPE Release)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED YES)

# Ensure using LLVM's LLD linker
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=lld -Wl,-segprot,__DATA_CONST,r,r")

# Include directories
include_directories(include)

# Pybind11
find_package(pybind11 REQUIRED)

# Source files for the Pybind11 module
file(GLOB PYSOURCES python_bindings/*.cpp python_bindings/**/*.cpp)

# Create the Pybind11 module
pybind11_add_module(libdescriptor ${PYSOURCES})

# Path to your custom library
set(MY_CUSTOM_LIB_PATH /Users/ec2-user/libdescriptor/bin)
find_library(DESCRIPTOR_LIB NAMES descriptor PATHS ${MY_CUSTOM_LIB_PATH})

if(NOT DESCRIPTOR_LIB)
    message(FATAL_ERROR "libdescriptor.dylib not found in ${MY_CUSTOM_LIB_PATH}")
endif()

# Link the Pybind11 module against the custom library
target_link_libraries(libdescriptor PUBLIC ${DESCRIPTOR_LIB})
target_include_directories(libdescriptor PUBLIC ${MY_CUSTOM_LIB_PATH})

3. otools输出(__DATA_CONST段信息)

(python3) ec2-user@ip-172-31-22-4 bin % otool -l ../bin/libdescriptor.dylib | grep -A 20 '__DATA_CONST'                          
  segname __DATA_CONST
   vmaddr 0x0000000000064000
   vmsize 0x0000000000004000
  fileoff 409600
 filesize 16384
  maxprot 0x00000003
 initprot 0x00000003
   nsects 2
    flags 0x0
Section
  sectname __got
   segname __DATA_CONST
      addr 0x0000000000064000
      size 0x0000000000000110
    offset 409600
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x00000006
 reserved1 0 (index into indirect symbol table)
 reserved2 0
Section
  sectname __const
   segname __DATA_CONST
      addr 0x0000000000064110
      size 0x0000000000000a30
    offset 409872
     align 2^3 (8)
    reloff 0
    nreloc 0
     flags 0x00000000
 reserved1 0
 reserved2 0
Load command 2
      cmd LC_SEGMENT_64
  cmdsize 312
  segname __DATA
   vmaddr 0x0000000000068000
   vmsize 0x0000000000064000
  fileoff 425984
 filesize 327680
  maxprot 0x00000003
 initprot 0x00000003
   nsects 3

原因分析

从otools输出可以明确:

  • __DATA_CONST段的maxprot和initprot均为0x3,对应权限是rw-(可读可写),但Mac OS标准中__DATA_CONST段应为只读(r--)
  • 段的flags为0x0,缺失SG_READ_ONLY标志(该标志对应值为0x1)

问题根源在于LLVM 13的lld链接器在Apple Silicon(M1)平台上,处理__DATA_CONST段权限时存在兼容性问题,再加上Enzyme LTO插件的介入,导致段权限和标志未正确设置。


解决步骤

1. 修复libdescriptor.dylib的段权限

修改libdescriptor的Makefile,在链接阶段显式指定__DATA_CONST段的权限和只读标志:

找到链接目标$(TARGET)的规则,添加-Wl,-segprot,__DATA_CONST,r,r和-Wl,-segattr,__DATA_CONST,SG_READ_ONLY参数:

$(TARGET): $(OBJFILES)
    $(CXX) -flto $(CXXFLAGS) -o $@ $^ -Wl,--lto-legacy-pass-manager -Wl,-mllvm -load=$(ENZYME_LIB) -Wl,-mllvm,-enzyme-loose-types -Wl,-segprot,__DATA_CONST,r,r -Wl,-segattr,__DATA_CONST,SG_READ_ONLY

说明:

  • -Wl,-segprot,__DATA_CONST,r,r:设置__DATA_CONST段的最大权限和初始权限为只读(r,r对应maxprot和initprot为0x1)
  • -Wl,-segattr,__DATA_CONST,SG_READ_ONLY:添加SG_READ_ONLY标志到__DATA_CONST段

修改后重新编译库:

make clean && make all

2. 调整PyBind11模块的链接配置

移除CMakefile中不必要的段权限设置(因为库本身已经修复),确保链接器一致性:

修改CMakefile中的CMAKE_SHARED_LINKER_FLAGS:

set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=lld")

然后重新构建PyBind11模块:

rm -rf build && mkdir build && cd build && cmake .. && make

验证修复结果

重新编译后,用otools检查__DATA_CONST段的权限和标志:

otool -l libdescriptor.dylib | grep -A 10 '__DATA_CONST'

确认输出中:

  • maxprot和initprot变为0x1(只读)
  • flags包含0x1(SG_READ_ONLY标志)

内容的提问来源于stack exchange,提问作者ipcamit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:24:53