private void parse(Object src, final long base) {
		boolean valid = false;

		long offset = base;
		long startOffset = offset;
		long endOffset = base;

		int nSignDwords = 0;

		try {

			// Scan forward looking for the Rich signature (or the PE signature, 
			// and we've gone too far) -- this sets the upper-bound (endOffset) of the table 
			for (int i = 0; i < MAX_TABLE_SEARCH_COUNT; i++, offset += 4) {
				int dw = readInt(src, offset);
				if (dw == RichHeader.IMAGE_RICH_SIGNATURE) {
					endOffset = offset + 8;// space for the signature and mask
					break;
				}
				if (dw == Constants.IMAGE_NT_SIGNATURE) {
					break;
				}
			}

			// Ensure we've determined the table-end
			if (endOffset != startOffset) {

				// The table mask follows; read it next
				offset += 4;
				mask = readInt(src, offset);

				// Now scan backwards until we find the DanS signature -- the lower-bound
				// of the table (startOffset);
				long _scanOffset = offset - 8;
				for (int i = 0; i < MAX_TABLE_SEARCH_COUNT; i--) {
					int dw = readInt(src, _scanOffset);
					if ((dw ^ mask) == RichHeader.IMAGE_DANS_SIGNATURE) {
						startOffset = (int) _scanOffset;
						nSignDwords++;
						valid = true;
						break;
					}
					_scanOffset -= 4;
					nSignDwords++;

					if (_scanOffset < base) {
						break;
					}
				}

				if (valid) {
					// Now that we know the bounds of the table, verify the padding bytes 
					offset = startOffset + 4;
					for (int i = 0; i < 3; i++, offset += 4) {
						int v = readInt(src, offset);
						if ((v ^ mask) != 0) {
							valid = false;
							break;
						}
					}
				}
			}

		}
		catch (IOException ioe) {
			valid = false;
		}

		if (!valid) {
			this.mask = -1;
			this.imageOffset = -1;
			this.size = 0;
			return;
		}

		// nSignDwords includes the 4 dwords of the header (DanS & padding dwords)...
		int numRecords = (nSignDwords / 2) - 2;

		this.imageOffset = startOffset;
		this.size = (int) (endOffset - imageOffset);

		records = new RichHeaderRecord[numRecords];

		offset = imageOffset + 16;// skip the DanS signature and padding dwords

		try {
			for (int i = 0; i < numRecords; i++) {

				int data1 = readInt(src, offset);
				int data2 = readInt(src, offset + 4);
				offset += 8;

				data1 ^= mask;
				data2 ^= mask;

				RichHeaderRecord rec = new RichHeaderRecord(i, data1, data2);

				records[i] = rec;
			}
		}
		catch (IOException ioe) {
			valid = false;
		}

		if (!valid) {
			records = new RichHeaderRecord[0];
			this.mask = -1;
			this.imageOffset = -1;
			this.size = 0;
			return;
		}

	}
Top level object model of the {@link RichHeader}.  Stores an array of
{@link RichHeaderRecord}.
Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/pe/RichTable.java