labath wrote:

> To answer your last question: because the plugins (which is really a 
> misnomer), as I understand it, are there to provide abstraction: the caller 
> shouldn't have to know what concrete instance an `ObjectFile` is. The 
> no-plugins-dependency enforces that at compile/link time.

This is my problem with that. You're saying the "caller shouldn't have to 
*know*" -- which is a statement about his state of mind. We can't enforce the 
state of mind through syntactic restrictions. We can prevent the caller from 
*saying* he expects a specific subclass, but there's not way to prevent code 
from expecting that implicitly (perhaps even without it knowing). Functions 
like `SupportsDebugMap` make it worse because they encourage writing code like 
that and that makes the plugin system (the abstractions created by it) less 
useful as a whole. Like, if I now wanted to create a new symbol file plugin 
that works only with a specific object file, do I add `SupportsPsym` to every 
object file plugin? Or we don't have to look at new plugins, we have two good 
examples already: SymbolFileBreakpad and SymbolFileJSON. Both of these 
currently depend on the their respective object file plugin. Should that be 
replaced by something else (and would the result be better if we did)?

Nonetheless, I agree that plugins should create abstractions, but I think it's 
important to think about who are those abstractions directed at. The core code 
definitely shouldn't need to "look behind the curtain" (ideally not even 
through calls like `SupportsDebugMap`), but I don't think that means that noone 
else isn't allowed to do that. This situation is really simple, so it doesn't 
demonstrate the full scope of the problem, which is why I want to go back to 
the ProcessCore->ObjectFile example.

ProcessElfCore needs to extract a lot of detailed information from 
ObjectFileELF. Same goes for ProcessMachCore. At some level, the information 
these two pairs are exchanging is the same (threads, registers, ...), so one 
could imagine a generic interface to pass this -- but would that help anything? 
I say "no", because you still want to have the two plugins to work in pair -- 
if you didn't, then you wouldn't need separate process core plugins. This setup 
would make sense if we had a generic ProcessCore class (not a plugin) which 
works off of information provided by the object plugins -- but that's not the 
situation we're in now. You can make the same case for dynamic loaders -- 
should MacOSX-DYLD work with ObjectFilePECOFF?


> TL;DR: My stance is that if there's a way to enforce the DAG, I'm totally 
> fine with allowing inter-plugin dependencies where they make sense. Barring 
> that I think the current rule, albeit overly strict, is the easiest way to 
> enforce we don't regress inter-plugin dependencies in general.

Enforcement is tricky, because "where it makes sense" is obviously a judgement 
call. It's also complicated by the fact that current graph is not a DAG. Linux 
linkers actually kind of enforce the graph implicitly, but since it's not a DAG 
now, we have a 
[workaround](https://github.com/llvm/llvm-project/blob/5c7bc6a0e6a5093812e6aa9719f7d98d14bb0015/lldb/source/Core/CMakeLists.txt#L92)
 and that prevents us catching any new bad deps. I guess it would be possible 
to do something similar to `NO_PLUGIN_DEPENDENCIES` in cmake, which only allows 
dependencies that we consider acceptable, though it's not foolproof: for 
example SymbolFileJSON doesn't list ObjectFileJSON in its cmake dependencies 
even though it definitely needs it.

I think the best we can do is some cmake check plus some documentation about 
which dependencies we consider "okay".
I don't think this can be foolproof though. Going by the examples above, I 
would say that we should permit dependencies on object file plugins from 
SymbolFiles, DynamicLoaders and Processes -- but there are still exceptions to 
that. For example, ProcessGdbRemote and DynamicLoaderStatic (and *maybe* 
SymbolFileDWARF) probably shouldn't depend on any specific ObjectFile plugin 
since they're meant to work with more than one (I guess that could be a general 
rule -- but it's not enforcable one).

A rule like "there shall be no inter-plugin dependencies" is easy to enforce 
and that makes it appealing, but I think it will be very hard for us to come 
into compliance with that (and I don't think we'd like the result even if we 
did). If we say some deps are okay, then a lot of things become automatically 
compliant, and we can focus on the high-value high-complexity deps like 
SymbolFile<->TypeSystem.

https://github.com/llvm/llvm-project/pull/139170
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to