Skip to content

[libc] [startup] add cmake function to merge separated crt1 objects #75413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

SchrodingerZhu
Copy link
Contributor

As part of startup refactoring, this patch adds a function to merge multiple objects into a single relocatable object:
cc -r obj1.o obj2.o -o obj.o

A relocatable object is an object file that is not fully linked into an executable or a shared library. It is an intermediate file format that can be passed into the linker.

A crt object can have arch-specific code and arch-agnostic code. To reduce code cohesion, the implementation is splitted into multiple units. As a result, we need to merge them into a single relocatable object.

@llvmbot llvmbot added the libc label Dec 14, 2023
@llvmbot
Copy link
Member

llvmbot commented Dec 14, 2023

@llvm/pr-subscribers-libc

Author: Schrodinger ZHU Yifan (SchrodingerZhu)

Changes

As part of startup refactoring, this patch adds a function to merge multiple objects into a single relocatable object:
cc -r obj1.o obj2.o -o obj.o

A relocatable object is an object file that is not fully linked into an executable or a shared library. It is an intermediate file format that can be passed into the linker.

A crt object can have arch-specific code and arch-agnostic code. To reduce code cohesion, the implementation is splitted into multiple units. As a result, we need to merge them into a single relocatable object.


Full diff: https://github.com/llvm/llvm-project/pull/75413.diff

1 Files Affected:

  • (modified) libc/startup/linux/CMakeLists.txt (+42-4)
diff --git a/libc/startup/linux/CMakeLists.txt b/libc/startup/linux/CMakeLists.txt
index 007aa30c17d6ab..5ca5010f6b1fe4 100644
--- a/libc/startup/linux/CMakeLists.txt
+++ b/libc/startup/linux/CMakeLists.txt
@@ -1,3 +1,42 @@
+# This function merges multiple objects into a single relocatable object
+#                     cc -r obj1.o obj2.o -o obj.o
+# A relocatable object is an object file that is not fully linked into an
+# executable or a shared library. It is an intermediate file format that can
+# be passed into the linker.
+# A crt object have arch-specific code and arch-agnostic code. To reduce code
+# cohesion, the implementation is splitted into multiple units. As a result,
+# we need to merge them into a single relocatable object.
+function(merge_relocatable_object name)
+  set(obj_list "")
+  set(fq_link_libraries "")
+  get_fq_deps_list(fq_dep_list ${ARGN})
+  foreach(target IN LISTS fq_dep_list)
+    list(APPEND obj_list "$<TARGET_OBJECTS:${target}>")
+    get_target_property(libs ${target} DEPS)
+    list(APPEND fq_link_libraries "${libs}")
+  endforeach()
+  get_fq_target_name(${name} fq_name)
+  add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
+    COMMAND ${CMAKE_CXX_COMPILER} -r ${obj_list} -o ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
+    DEPENDS ${obj_list}
+    COMMAND_EXPAND_LISTS
+  )
+  add_custom_target(${fq_name}.relocatable DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}.o)
+  add_library(${fq_name} OBJECT IMPORTED GLOBAL)
+  add_dependencies(${fq_name} ${fq_name}.relocatable)
+  target_link_libraries(${fq_name} INTERFACE ${fq_link_libraries})
+  set_target_properties(
+    ${fq_name} 
+    PROPERTIES
+      LINKER_LANGUAGE CXX
+      OBJECT_FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
+      IMPORTED_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/${name}.o
+      TARGET_TYPE ${OBJECT_LIBRARY_TARGET_TYPE}
+      DEPS "${fq_link_libraries}"
+  ) 
+endfunction()
+
 function(add_startup_object name)
   cmake_parse_arguments(
     "ADD_STARTUP_OBJECT"
@@ -34,11 +73,10 @@ endif()
 
 add_subdirectory(${LIBC_TARGET_ARCHITECTURE})
 
-add_startup_object(
+# TODO: factor out crt1 into multiple objects
+merge_relocatable_object(
   crt1
-  ALIAS
-  DEPENDS
-    .${LIBC_TARGET_ARCHITECTURE}.crt1
+  .${LIBC_TARGET_ARCHITECTURE}.crt1
 )
 
 add_startup_object(

@SchrodingerZhu
Copy link
Contributor Author

SchrodingerZhu commented Dec 15, 2023

@jhuber6 unfortunately, llvm_check_linker_flag does not really work on my computer (I thought it had worked but it was due to the cache). However, check_cxx_compiler_flag("-r" LIBC_LINKER_SUPPORTS_RELOCATABLE) works fine.

As part of startup refactoring, this patch adds a function to merge multiple objects into a single relocatable object:
                     cc -r obj1.o obj2.o -o obj.o

A relocatable object is an object file that is not fully linked into an executable or a shared library. It is an intermediate file format that can be passed into the linker.

A crt object can have arch-specific code and arch-agnostic code. To reduce code cohesion, the implementation is splitted into multiple units. As a result, we need to merge them into a single relocatable object.
@SchrodingerZhu SchrodingerZhu force-pushed the libc/startup-relocatable-obj branch from b1dee6c to dc5c97d Compare December 16, 2023 21:30
@SchrodingerZhu
Copy link
Contributor Author

Call for a merge if no further objection.

@nickdesaulniers nickdesaulniers merged commit 8bbeed0 into llvm:main Dec 20, 2023
@nickdesaulniers
Copy link
Member

ah, @SchrodingerZhu it looks like this broke the post submit bots:

@nickdesaulniers
Copy link
Member

FAILED: projects/libc/startup/linux/crt1.o 
: && /usr/bin/clang++ -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fno-omit-frame-pointer -O1 -fsanitize=address -fdiagnostics-color -g -r projects/libc/startup/linux/x86_64/CMakeFiles/libc.startup.linux.x86_64.crt1.dir/start.cpp.o -o projects/libc/startup/linux/crt1.o   && :
/usr/bin/ld: projects/libc/startup/linux/x86_64/CMakeFiles/libc.startup.linux.x86_64.crt1.dir/start.cpp.o: in function `_start':
/home/llvm-libc-buildbot/buildbot-worker/libc-x86_64-debian-fullbuild/libc-x86_64-debian-fullbuild-dbg-asan/llvm-project/libc/startup/linux/x86_64/start.cpp:144: multiple definition of `_start'; /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here

So it looks like _start is multiply defined:

  • crt1.o (from the system)
  • start.cpp.o (from llvmlibc)

Can you see if this can be fixed forward quickly? Otherwise I can revert.

I suspect -DLLVM_LIBC_FULL_BUILD=ON are the broken builds.

@SchrodingerZhu
Copy link
Contributor Author

SchrodingerZhu commented Dec 20, 2023

I actually had full build on locally. Inspecting the log, I think it is due to the unaligned behavior of the compilers. I suppose adding nostartfiles or freestanding should address the problem.

@SchrodingerZhu
Copy link
Contributor Author

@nickdesaulniers maybe revert it for now? I cannot work on this right now. I can get to this 2-3 hours later.

@SchrodingerZhu
Copy link
Contributor Author

Never mind. My meeting was canceled just now. I can submit a quick fix attempt with -nostdlib.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants