Files

95 lines
3.5 KiB
ObjectPascal

{********************************************************************
* Workaround for the Integrated Debugger Libc.execve bug *
* *
* (C) 2003 Andreas Hausladen (Andreas.Hausladen@gmx.de) *
* *
* *
* This software is provided 'as-is', without any express or *
* implied warranty. In no event will the author be held liable *
* for any damages arising from the use of this software. *
* *
* Permission is granted to anyone to use this software for any *
* purpose, including commercial applications, and to alter it *
* and redistribute it freely, subject to the following *
* restrictions: *
* *
* 1. The origin of this software must not be misrepresented, *
* you must not claim that you wrote the original software. *
* If you use this software in a product, an acknowledgment *
* in the product documentation would be appreciated but is *
* not required. *
* *
* 2. Altered source versions must be plainly marked as such, and *
* must not be misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source *
* distribution. *
* *
********************************************************************}
unit LibcExec;
{$ALIGN 8}
{$DEBUGINFO OFF}
{$RANGECHECKS OFF}
{$OVERFLOWCHECKS OFF}
{$STACKFRAMES OFF}
interface
implementation
{$IFDEF LINUX}
uses
Libc;
const
SYS_execve = 11;
{$OPTIMIZATION OFF}
function __execve(PathName: PChar; const argv: PPChar;
const envp: PPChar): Integer; cdecl;
begin
{ Do exactly the same things that the original execve@GLIBC_2.1 does. }
pthread_kill_other_threads_np;
Result := Libc.syscall(SYS_execve, PathName, argv, envp);
end;
{$OPTIMIZATION ON}
procedure InitExecveRedirect;
type
PRedirectCodeRec = ^TRedirectCodeRec;
TRedirectCodeRec = packed record
Code: Byte; // $E9 jmp Distance
Distance: Integer;
end;
const
Prot = PROT_READ or PROT_WRITE or PROT_EXEC;
Size = SizeOf(TRedirectCodeRec);
var
Addr: PRedirectCodeRec;
AlignedAddr: Cardinal;
PageSize: Cardinal;
begin
PageSize := getpagesize;
Addr := dlsym(Pointer(-1), 'execve');
{ Obtain write access to the memory page. }
AlignedAddr := Cardinal(Addr) and not (PageSize - 1);
if Cardinal(Addr) + Size >= AlignedAddr + PageSize then
PageSize := PageSize * 2;
mprotect(Pointer(AlignedAddr), PageSize, Prot);
{ Redirect Libc.execve }
Addr^.Code := $E9;
Addr^.Distance := Integer(@__execve) - Integer(Addr) - Size;
end;
initialization
{ Maybe someone has a better code to detect integrated debugging. This code
tests only for $DELPHI/$BCB environment variable. }
if (getenv('DELPHI') <> nil) or (getenv('BCB') <> nil) then
// started within Kylix IDE
InitExecveRedirect;
{$ENDIF}
end.