private boolean processManagedInstructions(Program program, AddressSetView set,
			TaskMonitor monitor, MessageLog log, CliMetadataRoot metadataRoot)
			throws CancelledException {
		// Determine if each instruction has something we should fix up.
		// Note that we use endsWith() instead of equals() because instructions can have prefixes.
		CliStreamMetadata metadataStream = metadataRoot.getMetadataStream();
		InstructionIterator instIter = program.getListing().getInstructions(set, true);
		while (instIter.hasNext()) {
			monitor.checkCancelled();
			try {
				Instruction inst = instIter.next();
				/* Base Instructions (Partition II.3) */
				if (inst.getMnemonicString().endsWith("ldstr")) {
					processUserString(metadataStream, inst);
				}
				else if (inst.getMnemonicString().endsWith("call")) {
					processControlFlowInstruction(program, metadataStream, inst,
						RefType.UNCONDITIONAL_CALL);
				}
				else if (inst.getMnemonicString().endsWith("calli")) {
					processControlFlowInstruction(program, metadataStream, inst,
						RefType.COMPUTED_CALL); // TODO: computed?
				}
				else if (inst.getMnemonicString().endsWith("jmp")) {
					processControlFlowInstruction(program, metadataStream, inst,
						RefType.UNCONDITIONAL_JUMP);
				}
				else if (inst.getMnemonicString().endsWith("ldftn")) {
					processGenericMetadataToken(metadataStream, inst);
					// TODO: how to say a method pointer is pushed onto the stack...
				}
				/* Object Model Instructions */
				else if (inst.getMnemonicString().endsWith("box") ||
					inst.getMnemonicString().endsWith("castclass") ||
					inst.getMnemonicString().endsWith("cpobj") ||
					inst.getMnemonicString().endsWith("initobj") ||
					inst.getMnemonicString().endsWith("isinst") ||
					inst.getMnemonicString().endsWith("ldelem") ||
					inst.getMnemonicString().endsWith("ldelema") ||
					inst.getMnemonicString().endsWith("ldfld") ||
					inst.getMnemonicString().endsWith("ldflda") ||
					inst.getMnemonicString().endsWith("ldobj") ||
					inst.getMnemonicString().endsWith("ldsfld") ||
					inst.getMnemonicString().endsWith("ldsflda") ||
					inst.getMnemonicString().endsWith("ldtoken") ||
					inst.getMnemonicString().endsWith("mkrefany") ||
					inst.getMnemonicString().endsWith("newarr") ||
					inst.getMnemonicString().endsWith("newobj") ||
					inst.getMnemonicString().endsWith("refanyval") ||
					inst.getMnemonicString().endsWith("sizeof") ||
					inst.getMnemonicString().endsWith("stelem") ||
					inst.getMnemonicString().endsWith("stfld") ||
					inst.getMnemonicString().endsWith("stobj") ||
					inst.getMnemonicString().endsWith("stsfld") ||
					inst.getMnemonicString().endsWith("unbox") ||
					inst.getMnemonicString().endsWith("unbox.any")) {
					processObjectModelInstruction(program, metadataStream, inst);
				}
				else if (inst.getMnemonicString().endsWith("callvirt")) {
					processControlFlowInstruction(program, metadataStream, inst,
						RefType.COMPUTED_CALL);
					// TODO: Computed call because this is a virtual function on an object
				}
				else if (inst.getMnemonicString().endsWith("constrained")) {
					CliAbstractTableRow tableRow = getRowForMetadataToken(metadataStream, inst);
					markMetadataRow(inst, tableRow, "Next instr type req'd to be: ", "",
						metadataStream);
				}
				else if (inst.getMnemonicString().endsWith("ldvirtfn")) {
					processObjectModelInstruction(program, metadataStream, inst);
					// TODO: ldvirtfn puts virtual method pointer on stack, see above for ldftn
				}
			}
			catch (Exception e) {
				e.printStackTrace();
				// TODO:
			}
		}

		return true;
	}
Finds CLI metadata tokens and renders them significantly more useful to the human user versus the CLI Virtual Execution System.
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/CliMetadataTokenAnalyzer.java