private void updateClassWithVfunctions(List<Vtable> vtables) throws Exception {

		for (Vtable vtable : vtables) {

			monitor.checkCancelled();

			Namespace classNamespace = vtable.getNamespace();

			RecoveredClass recoveredClass = getClass(classNamespace);

			if (recoveredClass == null) {
				Msg.error(this, "No class for vtable : " + classNamespace.getName());
				continue;
			}

			Address vftableAddress = vtable.getVfunctionTop();
			if (vftableAddress == null) {
				continue;
			}

			// get the number of bases
			// if only one then check no internal vtables
			// if more than one then check matches num internal vtables
			// match up the offset with the correct internal vftaable
			List<Vtable> internalVtables = vtable.getInternalVtables();
			List<Address> vftableAddresses = new ArrayList<Address>();
			vftableAddresses.add(vftableAddress);
			for (Vtable internalVtable : internalVtables) {
				monitor.checkCancelled();

				Address vfunctionTop = internalVtable.getVfunctionTop();
				if (vfunctionTop == null) {
					continue;
				}
				vftableAddresses.add(vfunctionTop);
			}
			Collections.sort(vftableAddresses);

			List<Long> baseOffsets = new ArrayList<Long>();
			GccTypeinfo referencedTypeinfo = vtable.getReferencedTypeinfo();
			List<BaseTypeinfo> baseTypeinfos = referencedTypeinfo.getBaseTypeinfos();
			List<BaseTypeinfo> allBaseTypeinfos = referencedTypeinfo.getAllBaseTypeinfos();

			// handle no parent case
			if (baseTypeinfos.size() == 0) {
				Symbol vftableSymbol = symbolTable.getPrimarySymbol(vftableAddress);
				updateClassWithVftable(recoveredClass, vftableSymbol, true, false);
				recoveredClass.addClassOffsetToVftableMapping(0, vftableAddress);
				continue;
			}

			// handle parent case
			for (BaseTypeinfo baseTypeinfo : baseTypeinfos) {
				monitor.checkCancelled();
				baseOffsets.add(baseTypeinfo.getOffset());
			}

			if (baseOffsets.size() != vftableAddresses.size()) {

				Msg.debug(this,
					classNamespace.getName(true) + " different size offset list and vftable list");

				if (allBaseTypeinfos.size() == vftableAddresses.size()) {
					Msg.debug(this, "Same number of total bases and vftables though");
				}
				continue;
			}

			for (int i = 0; i < baseOffsets.size(); i++) {

				BaseTypeinfo baseTypeinfo = baseTypeinfos.get(i);
				long offset = baseOffsets.get(i);

				Address correspondingVftableAddress = vftableAddresses.get(i);
				Symbol vftableSymbol = symbolTable.getPrimarySymbol(correspondingVftableAddress);

				updateClassWithVftable(recoveredClass, vftableSymbol, true, false);
				recoveredClass.addClassOffsetToVftableMapping((int) offset,
					correspondingVftableAddress);

				Namespace namespace = baseTypeinfo.getBaseTypeinfo().getNamespace();
				RecoveredClass baseClass = getClass(namespace);
				if (baseClass == null) {
					continue;
				}
				recoveredClass.addVftableToBaseClassMapping(correspondingVftableAddress, baseClass);

				//TODO: populate the new Vftable objects
			}
		}
	}
Create a map of addresses to a set of addresses that reference each address

@param refPairs list of reference address pairs
@throws CancelledException if cancelled
Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java