- Change one function pointer in Vtable - 25 Updates
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 04:30PM -0400 On 6/8/20 4:11 PM, Scott Newman wrote: >>> than cfront. >> Prove it. > There's no need to prove it. ABIs like COM f.e. rely on that. And if I'm not using COM? However, if you're correct, that is important information - what precisely does the documentation for COM say about the behavior when you modify a vtable? |
Scott Newman <scott69@gmail.com>: Jun 08 10:34PM +0200 >> There's no need to prove it. ABIs like COM f.e. rely on that. > And if I'm not using COM? The compilers still have to adhere to that. > However, if you're correct, that is important information - what > precisely does the documentation for COM say about the behavior > when you modify a vtable? The virtual functions still gonna be called. |
David Brown <david.brown@hesbynett.no>: Jun 08 10:36PM +0200 On 08/06/2020 22:15, Scott Newman wrote: > Then you assign the object adress to a volatile pointer so that > the compiler is inable to say if the object behind that pointer > might have changed. You are just inventing more and more silly, inefficient and undefined ways to handle something that is /extremely/ simple. Use a variable and a conditional, or a separate function pointer (according to taste), and be done with it. |
Scott Newman <scott69@gmail.com>: Jun 08 10:39PM +0200 > ways to handle something that is /extremely/ simple. Use a variable and > a conditional, or a separate function pointer (according to taste), and > be done with it. If you have a function-pointer in your class this would need additional space for each function. If you modify the vtable, this wouldn't need additional space. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 04:40PM -0400 On 6/8/20 4:13 PM, Scott Newman wrote: > Then you assign the object-address to a volatile pointer and that to > a non-volatile pointer. The compiler wouldn't be able to cache any > virtual functions across that assignemnt. I'm not quite sure what you mean by that. Could you give an example of actual code which implements your suggestion? It should, ideally, be short, complete, compilable, and executable - but if that's too difficult for you, I'll settle for an example where everything that needs to be declared "volatile" is so-declared, and where all the code that relies upon the fact that it is volatile is explicitly written out. Is that code any less complicated than simply defining a function pointer? The code which changes the vtable renders the behavior of your entire program undefined. As a result "this international standard imposes no requirements" on the behavior of such code (3.27). In particular, it does not require that your use of "volatile" be honored. |
Scott Newman <scott69@gmail.com>: Jun 08 10:43PM +0200 > I'm not quite sure what you mean by that. void f( ClassWithVirtual *cvw ) { cvw->vf(); // virtual modify_vtable( cvw ); // prevent caching of method-pointers cvw = (ClassWithVirtual *)(ClassWithVirtual *volatile)cvw; cvw->vf(); // virtual } |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 04:46PM -0400 On 6/8/20 4:34 PM, Scott Newman wrote: >>> There's no need to prove it. ABIs like COM f.e. rely on that. >> And if I'm not using COM? > The compilers still have to adhere to that. Even compilers targeting non-Windows platforms? >> precisely does the documentation for COM say about the behavior >> when you modify a vtable? > The virtual functions still gonna be called. I said "precisely" - please identify the exact document that says that, and the exact clause in that document which says so, and the precise wording used to say it. If you don't already know the answer to that last question, you're a fool for relying on the assumption that the answer supports your opinion. |
Scott Newman <scott69@gmail.com>: Jun 08 10:49PM +0200 >> The compilers still have to adhere to that. > Even compilers targeting non-Windows platforms? Yes, they al behave like Cfront. > I said "precisely" - please identify the exact document that says that, > and the exact clause in that document which says so, and the precise > wording used to say it. It's not the C++-standard that says that, it's reliable behaviour of the compilers. You're really a Noob that has no clue. |
Vir Campestris <vir.campestris@invalid.invalid>: Jun 08 09:56PM +0100 On 08/06/2020 21:18, Scott Newman wrote: > has derived from a class without virtual functions). > That's professional programming since this is 100% portable > and reliable. Up-thread people have already pointed out that some implementations put the vtbl pointer at the end of the object. Elsewhere it's been pointed out that the optimiser is free to bypass the vtbl entirely if it knows where it is (ought to be) pointing. I don't understand why you'd want to do this when a simple function pointer would have exactly the same effect in a portable manner. And not behave differently when you turn the optimiser on for a release build. Andy |
David Brown <david.brown@hesbynett.no>: Jun 08 10:58PM +0200 On 08/06/2020 22:39, Scott Newman wrote: > If you have a function-pointer in your class this would need additional > space for each function. If you modify the vtable, this wouldn't need > additional space. You must surely be trolling. But I think it must be obvious to the OP by now that everyone in this thread with any understanding of C++ is advising against the idea. |
Vir Campestris <vir.campestris@invalid.invalid>: Jun 08 10:00PM +0100 On 08/06/2020 18:49, Mr Flibble wrote: >> value outside the flow of operation as seen by the compiler. > Nonsense. Disable interrupts much? std::atomic is the superior solution > for ISRs these days. Stop living in the past. <snip> If you're going to use volatile (as I would have happily 30 years ago) you have to understand what it's going to do on your architecture with your cache design and a bunch of other features, such as the NUMA architecture in place. We still use volatile to poke HW registers. We know what it does on our platforms in that context. And it's all in the platform dependent code. Flibble is right here; volatile is not the right mechanism for passing data between threads; and in this context ISRs count as threads. std::atomic is designed for that, and will do the right thing in a portable manner. volatile is largely obsolete. Andy |
Scott Newman <scott69@gmail.com>: Jun 08 10:13PM +0200 > would result in your vtable modification sometimes being ignored, it can > also result in the confusing situation where your modification is > sometimes ignored, and sometime used. Then you assign the object-address to a volatile pointer and that to a non-volatile pointer. The compiler wouldn't be able to cache any virtual functions across that assignemnt. |
Paavo Helde <eesnimi@osa.pri.ee>: Jun 09 12:04AM +0300 08.06.2020 23:27 Frederick Gotham kirjutas: > I have the machine code of the program I want to alter. I don't have the original C++ code for it however I worked on it before and so I have a vague recollection of how it works. > The first thing I will do is search through the machine code for direct calls to the function which I intend to hijack (i.e. I will search for where the vtable accessing has been optimised away). I will replace these direct calls with actual use of the vtable. (There might not be any direct calls). Some calls may also be inlined by the optimizer, much more fun! > Next I will take the machine code of an existing interrupt routine and run it through a decompiler; I will add my own code for altering the vtable, and then I will compile the interrupt routine again and slot it back into the program. (I actually might not need to use a decompiler if I simply append my own machine code). > Testing will be very easy: It will either work or not work. > What I am proposing is an alternative to re-writing the original program, at a cost of a few thousand man-hours. This now makes more sense, as here you are working at the machine code/assembler level. This is the level where manipulating things like vtable is actually well defined, unlike at the C++ level. |
Scott Newman <scott69@gmail.com>: Jun 08 11:13PM +0200 > Up-thread people have already pointed out that some implementations put > the vtbl pointer at the end of the object. There's no such implementation. But it might be that when you derive from a class without virtual functions that the vtable-pointer is at the first address in the new class, i.e. before other data-members. > Elsewhere it's been pointed out that the optimiser is free to bypass > the vtbl entirely if it knows where it is (ought to be) pointing. I've shown in another post how to disable this behaviour, > I don't understand why you'd want to do this when a simple function > pointer would have exactly the same effect in a portable manner. A function-pointer in the vtable is more space-efficient. |
Scott Newman <scott69@gmail.com>: Jun 08 11:15PM +0200 > You must surely be trolling. Wrong. > But I think it must be obvious to the OP > by now that everyone in this thread with any understanding of C++ is > advising against the idea. Not necessary. There are safe, reliable and 100% portable ways to to that what the OP wants to do. That's absolutely professional sw-development. |
Scott Newman <scott69@gmail.com>: Jun 08 11:18PM +0200 > Flibble is right here; volatile is not the right mechanism for passing > data between threads; and in this context ISRs count as threads. There's one exception: you might use a volatile bool for a stop-flag. I.e. you might f.e. say ... while( !::stop ); ... instead of ... while( !stop.load( memory_order_relaxed ); I think the first one is more readable. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 05:21PM -0400 On 6/8/20 4:49 PM, Scott Newman wrote: > > and the exact clause in that document which says so, and the precise > > wording used to say it. > It's not the C++-standard that says that, ... I didn't say "C++-standard" - I just said "the exact document". The relevant document should be one that describes COM, which certainly isn't the C++ standard. > ... it's reliable behaviour More accurately, it's behavior that you've decided to rely upon. Without any document actually guaranteeing that it will actually work, relying upon that behavior is a pretty stupid thing to do. It might fail the very next time that you decide to rely upon it. > of the compilers. You're really a Noob that has no clue. On the contrary - I've been programming computers since roughly 1974, and have been earning an income as a computer programmer since 1979. And in all that time, one of the most common Noob errors I've seen has been for a Noob to be familiar with only one way of doing something, and assuming that it was the only way to do that thing. When I started out as a programmer, the catch phrase for that error was "All the world's a Vax". A few decades ago, it switched over to "All the world's a PC". I don't remember ever falling into that trap. It helped that my first three programming languages were Fortran, Basic, and APL - which prevented me from acquiring the delusion that every language works basically the same way. And it wasn't very long after I started programming professionally that I had experience with Unix, PC-DOS, Windows, CP-M, and Vax VMS, so I also avoided acquiring the delusion that all operating systems were pretty much the same. |
Scott Newman <scott69@gmail.com>: Jun 08 11:23PM +0200 > On the contrary - I've been programming computers since roughly 1974, Then you should have noticed that all C++-implementation behave like I describe. |
Paavo Helde <eesnimi@osa.pri.ee>: Jun 09 12:23AM +0300 08.06.2020 23:39 Scott Newman kirjutas: > If you have a function-pointer in your class this would need additional > space for each function. If you modify the vtable, this wouldn't need > additional space. I see during your long carrier you have not learned about the 'static' keyword, you might want to look it up. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 05:24PM -0400 On 6/8/20 4:43 PM, Scott Newman wrote: > cvw = (ClassWithVirtual *)(ClassWithVirtual *volatile)cvw; > cvw->vf(); // virtual > } OK - what I'm looking for is a little bit more detailed than that. In particular: What is the declaration for vf()? This is relatively minor, I just want to be certain what you're talking about. What is the definition of modify_vtable()? This is the most important part of what I was asking about. |
Scott Newman <scott69@gmail.com>: Jun 08 11:26PM +0200 >> additional space. > I see during your long carrier you have not learned about the 'static' > keyword, you might want to look it up. LOL, you're so stupid ! static wouldn't help you here when you need a vtable-like per-object dispatch. |
Scott Newman <scott69@gmail.com>: Jun 08 11:28PM +0200 Am 08.06.2020 um 23:24 schrieb James Kuyper: > particular: > What is the declaration for vf()? This is relatively minor, I just want > to be certain what you're talking about. It's just a virtual function whose vtable-pointer is modified by modify_vtable(). It's assigned to itself through a volatile pointer to prevent caching of the vtable-entry of vf. That's professional, reliable sw-development and you're a Noob. |
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 05:33PM -0400 On 6/8/20 5:13 PM, Scott Newman wrote: >> Up-thread people have already pointed out that some implementations put >> the vtbl pointer at the end of the object. > There's no such implementation. According to <https://en.wikipedia.org/wiki/Virtual_method_table>, "Many compilers place the virtual table pointer as the last member of the object; other compilers place it as the first; portable source code works either way.[2] For example, g++ previously placed the pointer at the end of the object.[3]" You don't have to trust Wikipedia about that; [2] and [3] refer to the bibliography. [3] refers to <https://web.archive.org/web/20110725153606/http://www.codesourcery.com/public/cxx-abi/cxx-closed.html>, which says, among other things: " [990617 All] Given a Vptr and only non-polymorphic bases, which (Vptr or base) goes at offset 0? HP: Vptr at end, but IA-64 is different because no load displacement Sun: Vptr at 0 probably preferred g++: Vptr at end today" |
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jun 08 02:34PM -0700 >> wording used to say it. > It's not the C++-standard that says that, it's reliable behaviour > of the compilers. You're really a Noob that has no clue. Even being right wouldn't justify this level of arrogance. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */ |
Scott Newman <scott69@gmail.com>: Jun 08 11:35PM +0200 > the object; other compilers place it as the first; portable source code > works either way.[2] For example, g++ previously placed the pointer at > the end of the object.[3]" That's not possible because the object's derived classes are growing at the end. So this is nonsense. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment