set(CMAKE_LDR_PE_HELPER_STANDARD_LIBRARIES "-lgcc" CACHE STRING "Standard C Libraries")
endif()
+if(NOT MSVC)
+###
+### For GCC
+###
+function(add_linker_script _target _linker_script_file)
+ get_filename_component(_file_full_path ${_linker_script_file} ABSOLUTE)
+ add_target_link_flags(${_target} "-Wl,-T,${_file_full_path}")
+
+ # Unfortunately LINK_DEPENDS is ignored in non-Makefile generators (for now...)
+ # See also http://www.cmake.org/pipermail/cmake/2010-May/037206.html
+ add_target_property(${_target} LINK_DEPENDS ${_file_full_path})
+endfunction()
+
+else()
+###
+### For MSVC
+###
+function(add_linker_script _target _linker_script_file)
+ get_filename_component(_file_full_path ${_linker_script_file} ABSOLUTE)
+ get_filename_component(_file_name ${_linker_script_file} NAME)
+ set(_generated_file_path_prefix "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_target}.dir/${_file_name}")
+
+ # Generate the ASM module containing sections specifications and layout.
+ set(_generated_file "${_generated_file_path_prefix}.S")
+ add_custom_command(
+ OUTPUT ${_generated_file}
+ COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${_file_full_path}" "${_generated_file}"
+ DEPENDS ${_file_full_path})
+ set_source_files_properties(${_generated_file} PROPERTIES LANGUAGE "ASM" GENERATED TRUE)
+ add_asm_files(freeldr_linker_file ${_generated_file})
+
+ # Generate the C module containing extra sections specifications and layout,
+ # as well as comment-type linker #pragma directives.
+ set(_generated_file "${_generated_file_path_prefix}.c")
+ add_custom_command(
+ OUTPUT ${_generated_file}
+ COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${_file_full_path}" "${_generated_file}"
+ DEPENDS ${_file_full_path})
+ set_source_files_properties(${_generated_file} PROPERTIES LANGUAGE "C" GENERATED TRUE)
+ list(APPEND freeldr_linker_file ${_generated_file})
+
+ # Add both files to the sources of the target.
+ target_sources(${_target} PRIVATE ${freeldr_linker_file})
+
+ # Create the additional linker response file.
+ set(_generated_file "${_generated_file_path_prefix}.rsp")
+ if(USE_CLANG_CL)
+ set(_no_std_includes_flag "-nostdinc")
+ else()
+ set(_no_std_includes_flag "/X")
+ endif()
+ add_custom_command(
+ #OUTPUT ${_generated_file}
+ TARGET ${_target} PRE_LINK
+ COMMAND ${CMAKE_C_COMPILER} /nologo ${_no_std_includes_flag} /D__LINKER__ /EP /c "${_file_full_path}" > "${_generated_file}"
+ DEPENDS ${_file_full_path}
+ VERBATIM)
+ set_source_files_properties(${_generated_file} PROPERTIES GENERATED TRUE)
+ add_target_link_flags(${_target} "@${_generated_file}")
+
+ # Unfortunately LINK_DEPENDS is ignored in non-Makefile generators (for now...)
+ # See also http://www.cmake.org/pipermail/cmake/2010-May/037206.html
+ add_target_property(${_target} LINK_DEPENDS ${_generated_file})
+endfunction()
+
+endif()
+
+
if(MSVC)
# We don't need hotpatching
replace_compile_flags("/hotpatch" " ")
add_target_link_flags(freeldr_pe "/ignore:4078 /ignore:4254 /DRIVER")
add_target_link_flags(freeldr_pe_dbg "/ignore:4078 /ignore:4254 /DRIVER")
else()
- add_target_link_flags(freeldr_pe "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:INIT=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text")
- add_target_link_flags(freeldr_pe_dbg "/ignore:4078 /ignore:4254 /DRIVER /FIXED /ALIGN:0x400 /SECTION:.text,ERW /SECTION:.data,RW /MERGE:.text16=.text /MERGE:INIT=.text /MERGE:.data=.text /MERGE:.rdata=.text /MERGE:.bss=.text")
+ add_target_link_flags(freeldr_pe "/ignore:4078 /ignore:4254 /DRIVER /FIXED /FILEALIGN:0x200 /ALIGN:0x200")
+ add_linker_script(freeldr_pe freeldr_i386.msvc.lds)
+ add_target_link_flags(freeldr_pe_dbg "/ignore:4078 /ignore:4254 /DRIVER /FIXED /FILEALIGN:0x200 /ALIGN:0x200")
+ add_linker_script(freeldr_pe_dbg freeldr_i386.msvc.lds)
endif()
else()
- add_target_link_flags(freeldr_pe "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lds")
- add_target_link_flags(freeldr_pe_dbg "-Wl,--exclude-all-symbols,--file-alignment,0x1000,-T,${CMAKE_CURRENT_SOURCE_DIR}/freeldr_i386.lds")
+ add_target_link_flags(freeldr_pe "-Wl,--strip-all,--exclude-all-symbols,--file-alignment,0x200,--section-alignment,0x200")
+ add_linker_script(freeldr_pe freeldr_i386.lds)
+ add_target_link_flags(freeldr_pe_dbg "-Wl,--exclude-all-symbols,--file-alignment,0x200,--section-alignment,0x200")
+ add_linker_script(freeldr_pe_dbg freeldr_i386.lds)
endif()
set_image_base(freeldr_pe 0x10000)
#include <arch/pc/x86common.h>
EXTERN BootMain:PROC
+// EXTERN cmdline:DWORD
+
+#ifdef _USE_ML
+EXTERN __bss_start__:FWORD
+EXTERN __bss_end__:FWORD
+#endif
.code64
mov eax, dword ptr [BSS_RealModeEntry]
mov dword ptr [AddressOfRealModeEntryPoint], eax
- /* GO! */
+ /* Clean out BSS */
+ xor rax, rax
+ mov rdi, offset __bss_start__
+ mov rcx, offset __bss_end__ + 7
+ sub rcx, rdi
+ shr rcx, 3
+ rep stosq
+
+ /* Pass the command line to BootMain */
+ // mov rcx, offset cmdline
xor rcx, rcx
+
+ /* GO! */
call BootMain
/* We should never get here */
stop:
- jmp stop
+ jmp short stop
nop
nop
EXTERN _InitIdt:PROC
EXTERN _i386Idt:DWORD
//EXTERN _i386idtptr:FWORD
+// EXTERN cmdline:DWORD
+
+#ifdef _USE_ML
+EXTERN __bss_start__:DWORD
+EXTERN __bss_end__:DWORD
+#endif
.code32
_FrldrStartup:
+ASSUME /*CS:_TEXT,*/ DS:_DATA, ES:_DATA, FS:_DATA, GS:_DATA, SS:_DATA
+
/* Store BootDrive and BootPartition */
mov byte ptr ds:[_FrldrBootDrive], dl
xor eax, eax
mov eax, dword ptr ds:[BSS_RealModeEntry]
mov dword ptr ds:[SwitchToReal16Address], eax
- /* Initialize the idt */
- call _InitIdt
-
-#ifndef _USE_ML
- /* Clean out bss */
+ /* Clean out BSS */
xor eax, eax
mov edi, offset __bss_start__
mov ecx, offset __bss_end__ + 3
shr ecx, 2
rep stosd
+ /* Initialize the idt */
+ call _InitIdt
+
/* Pass the command line to BootMain */
- mov eax, offset cmdline
-#else
+ // mov eax, offset cmdline
xor eax, eax
-#endif
/* GO! */
push eax
/* We should never get here */
stop:
- jmp stop
+ jmp short stop
nop
nop
mov ss, ax
/* Save 32-bit stack pointer */
- mov dword ptr [stack32], esp
+ mov dword ptr ds:[stack32], esp
/* jmp to 16-bit segment to set the limit correctly */
.byte HEX(0ea) // jmp far RMODE_CS:switch_to_real16
.word HEX(27) /* Limit */
.long gdt /* Base Address */
-/* Real-mode IDT pointer */
-rmode_idtptr:
- .word HEX(3ff) /* Limit */
- .long 0 /* Base Address */
-
+// See _i386IdtDescriptor
PUBLIC i386idtptr
i386idtptr:
.word 255 /* Limit */
*(SORT(.rdata*))
}
+ /*
+ * LD needs an explicit .edata block to make the binary correctly export
+ * symbols, otherwise, if .edata is merged with another section (e.g. .rdata)
+ * the exports are not exported!
+ */
.edata BLOCK(__file_alignment__) :
{
*(.edata)
--- /dev/null
+/*****************************************************************************\
+ *** MSVC Linker Script File -- Sections specifications & layout ***
+\*****************************************************************************/
+
+#ifndef _MSC_VER
+#error This file must be used only with the MSVC compiler and linker.
+#endif
+
+#if defined(__LINKER__)
+/*********************************\
+ ** Linker response file **
+\*********************************/
+
+// /LAST:.bss
+/LAST:.data
+
+#elif !defined(_USE_ML)
+/*********************************\
+ ** C Linker #pragma directives **
+\*********************************/
+
+/*
+ * Notes about automatic LINK.EXE behaviour that cannot be changed:
+ *
+ * - If a .data section is present, the .bss section is appended to it in case
+ * both of these have either Initialized or Uninitialized data (which is the
+ * case, unless one has manually modified the attributes).
+ *
+ * - If the /DRIVER flag is NOT used, and if both the .rdata and the .edata
+ * sections (read-only data and exports, respectively) have the same
+ * attributes, the .edata section is appended to the .rdata section.
+ * Otherwise they are kept separated, unless an explicit /MERGE is used.
+ */
+
+#pragma comment(linker, "/SECTION:.text,ERW /SECTION:.data,RW /MERGE:INIT=.text /MERGE:.edata=.rdata")
+
+#endif
+
+
+#if defined(_USE_ML) // && !defined(__LINKER__)
+/************************\
+ ** ASM definitions **
+\************************/
+
+#include <asm.inc>
+
+/*
+#pragma bss_seg(".bss")
+// __declspec(allocate(".bss"))
+void* __bss_start__;
+#pragma bss_seg()
+*/
+_BSS1 SEGMENT 'BSS' ALIAS('.bss')
+PUBLIC __bss_start__
+__bss_start__:
+ .long ?
+_BSS1 ENDS
+
+/*
+#pragma bss_seg(".bss$ZZZ")
+// __declspec(allocate(".bss$ZZZ"))
+void* __bss_end__;
+#pragma bss_seg()
+*/
+_BSS2 SEGMENT 'BSS' ALIAS('.bss$ZZZ')
+PUBLIC __bss_end__
+__bss_end__:
+ .long ?
+_BSS2 ENDS
+
+END
+
+#elif !defined(__LINKER__)
+/************************\
+ ** C definitions **
+\************************/
+
+#endif
extern char __ImageBase;
#ifdef __GNUC__
-/* .text, .edata and .bss */
+/* .text/.data/.rdata, .edata and .bss */
#define FREELDR_SECTION_COUNT 3
#else
#ifdef _M_AMD64
-/* .text and .pdata */
-#define FREELDR_SECTION_COUNT 2
+/* .text, .rdata/.edata, .pdata and .data/.bss */
+#define FREELDR_SECTION_COUNT 4
#else
-/* .text and .edata */
-#define FREELDR_SECTION_COUNT 2
+/* .text, .rdata/.edata and .data/.bss */
+#define FREELDR_SECTION_COUNT 3
#endif
#endif