/** * Written in the D programming language. * This module provides Win32-specific support for sections. * * Copyright: Copyright Digital Mars 2008 - 2012. * License: Distributed under the * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). * (See accompanying file LICENSE) * Authors: Walter Bright, Sean Kelly, Martin Nowak * Source: $(DRUNTIMESRC src/rt/_sections_win64.d) */ module rt.sections_win64; version(CRuntime_Microsoft): // debug = PRINTF; debug(PRINTF) import core.stdc.stdio; import core.stdc.stdlib : malloc, free; import rt.deh, rt.minfo; struct SectionGroup { static int opApply(scope int delegate(ref SectionGroup) dg) { return dg(_sections); } static int opApplyReverse(scope int delegate(ref SectionGroup) dg) { return dg(_sections); } @property immutable(ModuleInfo*)[] modules() const { return _moduleGroup.modules; } @property ref inout(ModuleGroup) moduleGroup() inout { return _moduleGroup; } version(Win64) @property immutable(FuncTable)[] ehTables() const { auto pbeg = cast(immutable(FuncTable)*)&_deh_beg; auto pend = cast(immutable(FuncTable)*)&_deh_end; return pbeg[0 .. pend - pbeg]; } @property inout(void[])[] gcRanges() inout { return _gcRanges[]; } private: ModuleGroup _moduleGroup; void[][1] _gcRanges; } void initSections() { _sections._moduleGroup = ModuleGroup(getModuleInfos()); // the ".data" image section includes both object file sections ".data" and ".bss" _sections._gcRanges[0] = findImageSection(".data"); debug(PRINTF) printf("found .data section: [%p,+%llx]\n", _sections._gcRanges[0].ptr, cast(ulong)_sections._gcRanges[0].length); } void finiSections() { .free(cast(void*)_sections.modules.ptr); } void[] initTLSRanges() { auto pbeg = cast(void*)&_tls_start; auto pend = cast(void*)&_tls_end; return pbeg[0 .. pend - pbeg]; } void finiTLSRanges(void[] rng) { } void scanTLSRanges(void[] rng, scope void delegate(void* pbeg, void* pend) nothrow dg) nothrow { dg(rng.ptr, rng.ptr + rng.length); } private: __gshared SectionGroup _sections; extern(C) { extern __gshared void* _minfo_beg; extern __gshared void* _minfo_end; } immutable(ModuleInfo*)[] getModuleInfos() out (result) { foreach(m; result) assert(m !is null); } body { auto m = (cast(immutable(ModuleInfo*)*)&_minfo_beg)[1 .. &_minfo_end - &_minfo_beg]; /* Because of alignment inserted by the linker, various null pointers * are there. We need to filter them out. */ auto p = m.ptr; auto pend = m.ptr + m.length; // count non-null pointers size_t cnt; for (; p < pend; ++p) { if (*p !is null) ++cnt; } auto result = (cast(immutable(ModuleInfo)**).malloc(cnt * size_t.sizeof))[0 .. cnt]; p = m.ptr; cnt = 0; for (; p < pend; ++p) if (*p !is null) result[cnt++] = *p; return cast(immutable)result; } extern(C) { /* Symbols created by the compiler/linker and inserted into the * object file that 'bracket' sections. */ extern __gshared { void* __ImageBase; void* _deh_beg; void* _deh_end; } extern { int _tls_start; int _tls_end; } } ///////////////////////////////////////////////////////////////////// enum IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ struct IMAGE_DOS_HEADER // DOS .EXE header { ushort e_magic; // Magic number ushort[29] e_res2; // Reserved ushorts int e_lfanew; // File address of new exe header } struct IMAGE_FILE_HEADER { ushort Machine; ushort NumberOfSections; uint TimeDateStamp; uint PointerToSymbolTable; uint NumberOfSymbols; ushort SizeOfOptionalHeader; ushort Characteristics; } struct IMAGE_NT_HEADERS { uint Signature; IMAGE_FILE_HEADER FileHeader; // optional header follows } struct IMAGE_SECTION_HEADER { char[8] Name; union { uint PhysicalAddress; uint VirtualSize; } uint VirtualAddress; uint SizeOfRawData; uint PointerToRawData; uint PointerToRelocations; uint PointerToLinenumbers; ushort NumberOfRelocations; ushort NumberOfLinenumbers; uint Characteristics; } bool compareSectionName(ref IMAGE_SECTION_HEADER section, string name) nothrow { if (name[] != section.Name[0 .. name.length]) return false; return name.length == 8 || section.Name[name.length] == 0; } void[] findImageSection(string name) nothrow { if (name.length > 8) // section name from string table not supported return null; IMAGE_DOS_HEADER* doshdr = cast(IMAGE_DOS_HEADER*) &__ImageBase; if (doshdr.e_magic != IMAGE_DOS_SIGNATURE) return null; auto nthdr = cast(IMAGE_NT_HEADERS*)(cast(void*)doshdr + doshdr.e_lfanew); auto sections = cast(IMAGE_SECTION_HEADER*)(cast(void*)nthdr + IMAGE_NT_HEADERS.sizeof + nthdr.FileHeader.SizeOfOptionalHeader); for(ushort i = 0; i < nthdr.FileHeader.NumberOfSections; i++) if (compareSectionName (sections[i], name)) return (cast(void*)&__ImageBase + sections[i].VirtualAddress)[0 .. sections[i].VirtualSize]; return null; }