unit FastMM_OSXUtil; interface type LPCSTR = PAnsiChar; LPSTR = PAnsiChar; DWORD = Cardinal; BOOL = Boolean; PSystemTime = ^TSystemTime; _SYSTEMTIME = record wYear: Word; wMonth: Word; wDayOfWeek: Word; wDay: Word; wHour: Word; wMinute: Word; wSecond: Word; wMilliseconds: Word; end; TSystemTime = _SYSTEMTIME; SYSTEMTIME = _SYSTEMTIME; SIZE_T = NativeUInt; PUINT_PTR = ^UIntPtr; const PAGE_NOACCESS = 1; PAGE_READONLY = 2; PAGE_READWRITE = 4; PAGE_WRITECOPY = 8; PAGE_EXECUTE = $10; PAGE_EXECUTE_READ = $20; PAGE_EXECUTE_READWRITE = $40; PAGE_GUARD = $100; PAGE_NOCACHE = $200; MEM_COMMIT = $1000; MEM_RESERVE = $2000; MEM_DECOMMIT = $4000; MEM_RELEASE = $8000; MEM_FREE = $10000; MEM_PRIVATE = $20000; MEM_MAPPED = $40000; MEM_RESET = $80000; MEM_TOP_DOWN = $100000; EXCEPTION_ACCESS_VIOLATION = DWORD($C0000005); //function GetModuleHandleA(lpModuleName: LPCSTR): HMODULE; stdcall; function GetEnvironmentVariableA(lpName: LPCSTR; lpBuffer: LPSTR; nSize: DWORD): DWORD; stdcall; overload; function DeleteFileA(lpFileName: LPCSTR): BOOL; stdcall; function VirtualAlloc(lpvAddress: Pointer; dwSize: SIZE_T; flAllocationType, flProtect: DWORD): Pointer; stdcall; function VirtualFree(lpAddress: Pointer; dwSize, dwFreeType: Cardinal): LongBool; stdcall; procedure RaiseException(dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWORD; lpArguments: PUINT_PTR); stdcall; type PSecurityAttributes = ^TSecurityAttributes; _SECURITY_ATTRIBUTES = record nLength: DWORD; lpSecurityDescriptor: Pointer; bInheritHandle: BOOL; end; TSecurityAttributes = _SECURITY_ATTRIBUTES; SECURITY_ATTRIBUTES = _SECURITY_ATTRIBUTES; const GENERIC_READ = DWORD($80000000); GENERIC_WRITE = $40000000; OPEN_ALWAYS = 4; FILE_ATTRIBUTE_NORMAL = $00000080; FILE_BEGIN = 0; FILE_CURRENT = 1; FILE_END = 2; INVALID_SET_FILE_POINTER = DWORD(-1); procedure GetLocalTime(var lpSystemTime: TSystemTime); stdcall; function CreateFileA(lpFileName: LPCSTR; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; function SetFilePointer(hFile: THandle; lDistanceToMove: Longint; lpDistanceToMoveHigh: PLongInt; dwMoveMethod: DWORD): DWORD; stdcall; function CloseHandle(hObject: THandle): BOOL; stdcall; implementation uses Posix.Stdlib, Posix.Unistd, Posix.SysMman, Posix.Fcntl, Posix.SysStat, Posix.SysTime, Posix.Time, Posix.Errno, Posix.Signal; function CreateFileA(lpFileName: LPCSTR; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): THandle; stdcall; var Flags: Integer; FileAccessRights: Integer; begin // O_RDONLY open for reading only // O_WRONLY open for writing only // O_RDWR open for reading and writing // O_NONBLOCK do not block on open or for data to become available // O_APPEND append on each write // O_CREAT create file if it does not exist // O_TRUNC truncate size to 0 // O_EXCL error if O_CREAT and the file exists // O_SHLOCK atomically obtain a shared lock // O_EXLOCK atomically obtain an exclusive lock // O_NOFOLLOW do not follow symlinks // O_SYMLINK allow open of symlinks // O_EVTONLY descriptor requested for event notifications only // O_CLOEXEC mark as close-on-exec Flags := 0; FileAccessRights := S_IRUSR or S_IWUSR or S_IRGRP or S_IWGRP or S_IROTH or S_IWOTH; case dwDesiredAccess and (GENERIC_READ or GENERIC_WRITE) of //= (GENERIC_READ or GENERIC_WRITE) then GENERIC_READ or GENERIC_WRITE: Flags := Flags or O_RDWR; GENERIC_READ: Flags := Flags or O_RDONLY; GENERIC_WRITE: Flags := Flags or O_WRONLY; else Exit(THandle(-1)); end; case dwCreationDisposition of // CREATE_NEW: // CREATE_ALWAYS: // OPEN_EXISTING: OPEN_ALWAYS: Flags := Flags or O_CREAT; // TRUNCATE_EXISTING: end; Result := THandle(__open(lpFileName, Flags, FileAccessRights)); // ShareMode // smode := Mode and $F0 shr 4; // if ShareMode[smode] <> 0 then // begin // LockVar.l_whence := SEEK_SET; // LockVar.l_start := 0; // LockVar.l_len := 0; // LockVar.l_type := ShareMode[smode]; // Tvar := fcntl(FileHandle, F_SETLK, LockVar); // Code := errno; // if (Tvar = -1) and (Code <> EINVAL) and (Code <> ENOTSUP) then // EINVAL/ENOTSUP - file doesn't support locking // begin // __close(FileHandle); // Exit; // end; end; type _LARGE_INTEGER = record case Integer of 0: ( LowPart: DWORD; HighPart: Longint); 1: ( QuadPart: Int64); end; function SetFilePointer(hFile: THandle; lDistanceToMove: Longint; lpDistanceToMoveHigh: PLongInt; dwMoveMethod: DWORD): DWORD; stdcall; var dist: _LARGE_INTEGER; begin dist.LowPart := lDistanceToMove; if Assigned(lpDistanceToMoveHigh) then dist.HighPart := lpDistanceToMoveHigh^ else dist.HighPart := 0; dist.QuadPart := lseek(hFile, dist.QuadPart, dwMoveMethod); // dwMoveMethod = same as in windows if dist.QuadPart = -1 then Result := DWORD(-1) else begin Result := dist.LowPart; if Assigned(lpDistanceToMoveHigh) then lpDistanceToMoveHigh^ := dist.HighPart; end; end; procedure GetLocalTime(var lpSystemTime: TSystemTime); stdcall; var T: time_t; TV: timeval; UT: tm; begin gettimeofday(TV, nil); T := TV.tv_sec; localtime_r(T, UT); lpSystemTime.wYear := UT.tm_year; lpSystemTime.wMonth := UT.tm_mon; lpSystemTime.wDayOfWeek := UT.tm_wday; lpSystemTime.wDay := UT.tm_mday; lpSystemTime.wHour := UT.tm_hour; lpSystemTime.wMinute := UT.tm_min; lpSystemTime.wSecond := UT.tm_sec; lpSystemTime.wMilliseconds := 0; end; function CloseHandle(hObject: THandle): BOOL; stdcall; begin Result := __close(hObject) = 0; end; function StrLen(const Str: PAnsiChar): Cardinal; begin Result := Length(Str); end; function StrLCopy(Dest: PAnsiChar; const Source: PAnsiChar; MaxLen: Cardinal): PAnsiChar; var Len: Cardinal; begin Result := Dest; Len := StrLen(Source); if Len > MaxLen then Len := MaxLen; Move(Source^, Dest^, Len * SizeOf(AnsiChar)); Dest[Len] := #0; end; function StrPLCopy(Dest: PAnsiChar; const Source: AnsiString; MaxLen: Cardinal): PAnsiChar; begin Result := StrLCopy(Dest, PAnsiChar(Source), MaxLen); end; function GetModuleHandle(lpModuleName: PWideChar): HMODULE; begin Result := 0; if lpModuleName = 'kernel32' then Result := 1; end; function GetModuleHandleA(lpModuleName: LPCSTR): HMODULE; stdcall; begin Result := GetModuleHandle(PChar(string(lpModuleName))); end; function GetEnvironmentVariableA(lpName: LPCSTR; lpBuffer: LPSTR; nSize: DWORD): DWORD; stdcall; overload; var Len: Integer; Env: string; begin env := string(getenv(lpName)); Len := Length(env); Result := Len; if nSize < Result then Result := nSize; StrPLCopy(lpBuffer, env, Result); if Len > nSize then SetLastError(122) //ERROR_INSUFFICIENT_BUFFER) else SetLastError(0); end; function DeleteFileA(lpFileName: LPCSTR): BOOL; stdcall; begin Result := unlink(lpFileName) <> -1; end; // ReservedBlock := VirtualAlloc(Pointer(DebugReservedAddress), 65536, MEM_RESERVE, PAGE_NOACCESS); function VirtualAlloc(lpvAddress: Pointer; dwSize: SIZE_T; flAllocationType, flProtect: DWORD): Pointer; stdcall; var PageSize: LongInt; AllocSize: LongInt; Protect: Integer; begin if lpvAddress <> nil then begin if flAllocationType <> MEM_RESERVE then Exit(0); if flProtect <> PAGE_NOACCESS then Exit(0); PageSize := sysconf(_SC_PAGESIZE); AllocSize := dwSize - (dwSize mod PageSize) + PageSize; Result := mmap(lpvAddress, AllocSize, PROT_NONE, MAP_PRIVATE or MAP_ANON, -1, 0); Exit; end; Result := malloc(dwSize); FillChar(Result^, dwSize, 0); //Result := valloc(dwSize); // FreeItem.Addr := mmap(nil, PageSize, PROT_WRITE or PROT_EXEC, // MAP_PRIVATE or MAP_ANON, -1, 0); end; function VirtualFree(lpAddress: Pointer; dwSize, dwFreeType: Cardinal): LongBool; stdcall; begin Result := True; if dwFreetype = MEM_RELEASE then begin if lpAddress = Pointer($80800000) then munmap(lpAddress, dwSize) else free(lpAddress); end; end; procedure RaiseException(dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWORD; lpArguments: PUINT_PTR); stdcall; begin WriteLN('ACCESS VIOLATION (set breakpoint in FastMM_OSXUtil: RaiseException for easier debugging)'); kill(getppid, SIGSEGV); asm int 3; end; end; end.