We have some ancient Delphi code (might have even originated as Turbo Pascal code) that uses {$I-}, aka {$IOCHECKS
OFF}, which makes the code use IOResult instead of exceptions for disk I/O errors.
I want to get rid of the {$I-} and bring this code forward into the 1990s, but to do that, I'd like to know what all is affected by {$IOCHECKS OFF}. Does this only affect the crufty old built-in I/O functions like AssignFile / Reset / Rewrite / Append / CloseFile? Or does it affect more modern things like TFileStream as well? More importantly, what else might be affected that I'm not thinking of? (Delphi Basics suggests that it also affects MkDir and RmDir. If it affects those, there have to be more.)
The Delphi 2007 Help topic "Input output checking (Delphi)" (ms-help://borland.bds5/devcommon/compdirsinput_outputchecking_xml.html) says that this affects "I/O procedure[s]", and that "I/O procedures are described in the Delphi Language Guide." This doesn't help much, since CodeGear has never shipped a Language Guide, and the last time Borland shipped one was Delphi 5.
Which functions and classes behave differently under {$I-}?
EDIT: The accepted answer gives some great background, but here's the quick summary in alphabetized list form: {$IOCHECKS OFF} only affects the following routines from the System unit.
Append
BlockRead
BlockWrite
ChDir
CloseFile
Eof
Eoln
Erase
FilePos
FileSize
Flush
MkDir
Read
Readln
Rename
Reset
Rewrite
RmDir
Seek
SeekEof
SeekEoln
SetLineBreakStyle
Truncate
Write
Writeln
Since $I is a compiler directive, it can only affect compiler-generated code, and it can only affect code that actually gets compiled.
For those two reasons, it cannot affect things like TFileStream. It's a class in Classes.pas, which is a unit you don't compile. Any code in it is not affected by the $I directive. Furthermore, the compiler doesn't treat that class specially in any way. It's just another ordinary class.
The $I directive affects the language built-in functions that you've mentioned. The compiler generates calls to those functions specially. It also affects calls to write, writeln, and readln. It should also affect BlockRead and BlockWrite.
You can check the source code. Anything that calls SetInOutRes is susceptible to $I. That includes functions that open files (Append, Reset, and Rewrite), as well as anything else that accepts a parameter of type file or TextFile (Flush, BlockRead, BlockWrite, Erase, FilePos, Seek, FileSize, Read, Readln, Write, Writeln, Rename, Eof, SeekEof, Eoln, SeekEol, Truncate, SetLineBreakStyle, and CloseFile). Also, anything that calls InOutError (ChDir, MkDir, amd RmDir).
Notably absent from the list is AssignFile. That function doesn't actually do any I/O. It just sets up the file record so that Append, Reset, and Rewrite will know what to do.
I should point out that looking at the source code is just inference. The $I directive controls whether the compiler will insert calls to the __IOTest function in your own code after you call certain other functions. That function checks the value of InOutRes, and if it's not zero, it raises a run-time error (which may yield an exception if SysUtils is included in your program). We can't check the source code to directly find out what functions are affected by $I (since it's only called in compiler-generated code), so we're really just looking for which functions set InOutRes, with the assumption that they wouldn't bother doing that if they didn't know the compiler would check for it afterward.
Related
In the glibc implementation of popen(), it specifies that
The popen() function shall ensure that any streams from previous popen() calls that remain open in the parent process are closed in the new child process.
Why? If the purpose is to avoid fd leaks, why not just close all open fds?
The glibc implementation of popen() uses fork(). Although there are dup2() and close() calls between fork() and exec(), is it possible to replace fork() by vfork() to improve performance?
Is the Linux implementation of popen() based on fork() rather than vfork()? Why (or why not)?
I'm going to write a bidirectional version of popen(), which returns two FILE*: one for read and one for write. How do I implement it correctly? It should be thread safe and no fd leaks. It is better if it is fast.
vfork(2) is obsolete (removed from POSIX2008), and fork(2) is quite efficient, since it uses copy-on-write techniques.
popen(3) cannot close all opened files, because it does not know them and cannot know which are relevant. Imagine a program which gets a socket and pass its file descriptor as an argument to the popen-ed command (or simply popen("time cat /etc/issue >&9; date","r")....). See also fcntl(2) with FD_CLOEXEC, open(2) with O_CLOEXEC, execve(2)
File descriptors are program-wide and process-wide scare resources and it is your responsability to manage them correctly. You should know which fd-s should be closed in your child process before execve. If you know what program is execve-d and what fds it needs, you can close all other fds (or most of them, perhaps with for (int i=STDERR_FILENO+1; i<64; i++) (void) close(i);) before execve.
If you are coding a reusable library, document its policy regarding file descriptors (and any other global process-wide resources) and probably use FD_CLOEXEC on any file descriptors it is obtaining itself (not as explicit argument or data), e.g. for internal use.
It looks like you are reinventing p2open (then you probably need to understand the implementation details of your FILE in your C standard library, or else use fdopen(3) with care and caution); you might find some implementation of it. Beware, the process using that probably need to have some event loop (e.g. above poll(2) ...) to avoid a potential deadlock (with both parent and child processes blocked on reading).
Did you consider using some existing event loop infrastructure (e.g. libevent, libev, glib from GTK, etc....)?
BTW Linux has several free software implementations for its C standard library. The GNU libc is quite common, but there is musl-libc and several others. Study the source code of your libc.
i use this code to determine if a specific module has been injected to my application's process
(i use it to prevent some Packet Sniffer Softwares)
Var
H:Cardinal;
Begin
H:= GetModuleHandle('WSock32.dll');
if H >0 then FreeLibrary(H);
end;
the problem is when i call Freelibrary it do nothing !
i don't wanna show message then terminate the application i just want to unload the injected module silently
thanks in advance
Well, first of all I'll attempt to answer the question as asked. And then, I'll try to argue that you are asking the wrong question.
Modules are reference counted. It's possible that there are multiple references to this module. So, keep calling FreeLibrary:
procedure ForceRemove(const ModuleName: string);
var
hMod: HMODULE;
begin
hMod := GetModuleHandle(PChar(ModuleName));
if hMod=0 then
exit;
repeat
until not FreeLibrary(hMod);
end;
If you were paranoid you might choose to add an alternative termination of the loop to avoid looping indefinitely.
I don't really know that this will work in your scenario. For instance, it's quite plausible that your process links statically to WSock32. In which case no amount of calling FreeLibrary will kick it out. And even if you could kick it out, the fact that your process statically linked to it probably means it's going to fail pretty hard.
Even if you can kick it out, it seems likely that other code in your process will hold references to functions in the module. And so you'll just fail somewhere else. I can think of very few scenarios where it makes sense to kick a module out of your process with complete disregard for the other users of that module.
Now, let's step back and look at what you are doing. You are trying to remove a standard system DLL from your process because you believe that it is only present because your process is having its packets sniffed. That seems unlikely to be true.
Since you state that your process is subject to packet sniffing attack. That means that the process is communicating over TCP/IP. Which means that it probably uses system modules to carry out that communication. One of which is WSock32. So you very likely link statically to WSock32. How is your process going to work if you kill one of the modules used to supply its functionality?
Are you quite sure that the presence of WSock32 in your process indicates that your process is under attack? If a packet sniffer was going to inject a DLL into your process, why would it inject the WSock32 system DLL? Did you check whether or not your process, or one of its dependencies, statically links to WSock32?
I rather suspect that you've just mis-diagnosed what is happening.
Some other points:
GetModuleHandle returns, and FreeLibrary accepts an HMODULE. For 32 bit that is compatible with Cardinal, but not for 64 bit. Use HMODULE.
The not found condition for GetModuleHandle is that the return value is 0. Nowhere in the documentation is it stated that a value greater than 0 indicates success. I realise that Cardinal and HMODULE are unsigned, and so <>0 is the same as >0, but it really makes no sense to test >0. It leaves the programmer thinking, "what is so special about <0?"
My delphi application runs scripts using JvInterpreter (from the Jedi project).
A feature I use is runtime evaluation of expressions.
Script Example:
[...]
ShowMessage(X_SomeName);
[...]
JvInterpreter doesn't know X_SomeName.
When X_SomeName's value is required the scripter calls its OnGetValue-callback.
This points to a function I handle. There I lookup X_SomeName's value and return it.
Then JvInterpreter calls ShowMessage with the value I provided.
Now I consider switching to DelphiWebScript since it has a proper debug-interface and should also be faster than JvInterpreter.
Problem: I didn't find any obvious way to implement what JvInterpreter does with its OnGetValue/OnSetValue functions, though.
X_SomeName should be considered (and actually is, most of the time) a variable which is handled by the host application.
Any Ideas?
Thanks!
You can do that through the language extension mechanism, which has a FindUnknownName method that allows to register symbols on the spot.
It is used in the asm lib module demo, and you can also check the new "AutoExternalValues" test case in ULanguageExtensionTests, which should be closer to what you're after.
Is it possible to unmangle names like these in Delphi?
If so, where do I get more information?
Example of an error message where it cannot find a certain entry in the dbrtl100.bpl
I want to know which exact function it cannot find (unit, class, name, parameters, etc).
---------------------------
myApp.exe - Entry Point Not Found
---------------------------
The procedure entry point #Dbcommon#GetTableNameFromSQLEx$qqrx17System#WideString25Dbcommon#IDENTIFIEROption could not be located in the dynamic link library dbrtl100.bpl.
---------------------------
OK
---------------------------
I know it is the method GetTableNameFromSQLEx in the Dbcommon unit (I have Delphi with the RTL/VCL sources), but sometimes I bump into apps where not all code is available for (yes, clients should always buy all the source code for 3rd party stuff, but sometimes they don't).
But say this is an example for which I do not have the code, or only the interface files (BDE.INT anyone?)
What parameters does it have (i.e. which potential overload)?
What return type does it have?
Is this mangling the same for any Delphi version?
--jeroen
Edit 1:
Thanks to Rob Kennedy: tdump -e dbrtl100.bpl does the trick. No need for -um at all:
C:\WINDOWS\system32>tdump -e dbrtl100.bpl | grep GetTableNameFromSQLEx
File STDIN:
00026050 1385 04AC __fastcall Dbcommon::GetTableNameFromSQLEx(const System::WideString, Dbcommon::IDENTIFIEROption)
Edit 2:
Thanks to TOndrej who found this German EDN article (English Google Translation).
That article describes the format pretty accurately, and it should be possible to create some Delphi code to unmangle this.
Pitty that the website the author mentions (and the email) are now dead, but good to know this info.
--jeroen
There is no function provided with Delphi that will unmangle function names, and I'm not aware of it being documented anywhere. Delphi in a Nutshell mentions that the "tdump" utility has a -um switch to make it unmangle symbols it finds. I've never tried it.
tdump -um -e dbrtl100.bpl
If that doesn't work, then it doesn't look like a very complicated scheme to unmangle yourself. Evidently, the name starts with "#" and is followed by the unit name and function name, separated by another "#" sign. That function name is followed by "$qqrx" and then the parameter types.
The parameter types are encoded using the character count of the type name followed by the same "#"-delimited format from before.
The "$" is necessary to mark the end of the function name and the start of the parameter types. The remaining mystery is the "qqrx" part. That's revealed by the article Tondrej found. The "qqr" indicates the calling convention, which in this case is register, a.k.a. fastcall. The "x" applies to the parameter and means that it's constant.
The return type doesn't need to be encoded in the mangled function name because overloading doesn't consider return types anyway.
Also see this article (in German).
I guess the mangling is probably backward-compatible, and new mangling schemes are introduced in later Delphi versions for new language features.
If you have C++Builder, check out $(BDS)\source\cpprtl\Source\misc\unmangle.c - it contains the source code for the unmangling mechanism used by TDUMP, the debugger and the linker. (C++Builder and Delphi use the same mangling scheme.)
From the Delphi 2007 source files:
function GetTableNameFromSQLEx(const SQL: WideString; IdOption: IDENTIFIEROption): WideString;
This seems to be the same version, since I also have the same .BPL in my Windows\System32 folder.
Source can be found in [Program Files folders]\CodeGear\RAD Studio\5.0\source\Win32\db
Borland/Codegear/Embarcadero has used this encoding for a while now and never gave many details about the .BPL format. I've never been very interested in them since I hate using runtime libraries in my projects. I prefer to compile them into my projects, although this will result in much bigger executables.
I am writing a unit test infrastructure for a large Delphi code base. I would like to link calls to pure functions in SysUtils.FileExists for example to a "MockSysUtils.FileExists" instead.
Creating a SysUtils unit with the same interface is not appreciated by the compiler.
What I am thinking of is to hook in my mock function at runtime. Is this possible nowadays?
Any other suggestions?
Regards,
Peter
Replacing a function at runtime is difficult but usually technically possible. "All" you need to do is:
take the address of the function in question
disassemble the first 5 bytes or so (to check for a RET instruction - very small routines may abut another routine, preventing you from replacing it)
change its page protection (with VirtualProtect) to be writable
rewrite the first 5 bytes with a JMP rel32 instruction (i.e. E9 <offset-to-your-func>)
implement your version function as normal, making sure it has the same arguments and calling convention as the function you are mocking
An easier approach would be to link against a different version of SysUtils.pas. That will require you to also recompile all the units in the RTL and VCL that depend on SysUtils.pas, but it is likely quite a bit easier than the function intrumentation approach described above.
The easiest approach is the language-level one, where either you don't directly rely on SysUtils at all (and so can switch at a higher level), or you modify the uses declaration to conditionally refer to a different unit.
You can do it with MadCodeHook. Use the HookCode function, give it the address of the function you want to replace and the address of the function you want to be called instead. It will give you back a function pointer that you can use for calling the original and for unhooking afterward. In essence, it implements the middle three steps of Barry's description.
I think MadCodeHook is free for personal use. If you're looking for something freer than that, you can try to find an old version of the Tnt Unicode controls. It used the same hooking technique to inject Unicode support into some of the VCL's code. You'll need an old version because more recent releases aren't free anymore. Find the OverwriteProcedure function in TntSystem.pas, which is also where you'll find examples of how to use it.
Code-hooking is nice because it doesn't require you to recompile the RTL and VCL, and it doesn't involve conditional compilation to control which functions are in scope. You can hook the code from your unit-test setup procedure, and the original code will never know the difference. It will think it's calling the original FileExists function (because it is), but when it gets there, it will immediately jump to your mocked version instead.
You could also just add a unit that only contains the functions you want to mock to the test unit's uses clause. Delphi will always use the function from the unit that is listed last. Unfortunately this would require you to change the unit you want to test.
Your Mock-Sysutils unit:
unit MockSysutils;
interface
function FileExists(...) ...
...
end.
Your unit, you want to test:
unit UnitTotest;
interface
uses
Sysutils,
MockSysUtils;
...
if FileExists(...) then
FileExists will now call the version from MockSysutils rather than from Sysutils.
Thanks,
yes, it would be great to have TSysUtils class for example instead that I could inherit with my MockSysUtils. But, that is not the case and the code base huge. It will be replaced bit by bit, but I wondered if there was a quick-start solution.
The first approach is ok for one function perhaps, but not in this case I guess.
I will go for the second approach.
This is slightly way out there but here is another alternative.
When building your unit tests and your main codebase to go with it, you could grep all the functions you wish to replace and specify the unit to use
Instead of
fileexists(MyFilename);
you could grep fileexists and replace with
MockTests.fileexists(MyFileName);
If you did this at build time (using automated build tools) it could easily be done and would provide you with the greatest flexibility. You could simply have a config file that listed all the functions to be replaced.