github.com/saferwall/pe@v1.5.2/dotnet_test.go (about)

     1  // Copyright 2018 Saferwall. All rights reserved.
     2  // Use of this source code is governed by Apache v2 license
     3  // license that can be found in the LICENSE file.
     4  
     5  package pe
     6  
     7  import (
     8  	"reflect"
     9  	"sort"
    10  	"strconv"
    11  	"testing"
    12  )
    13  
    14  func TestClrDirectoryHeaders(t *testing.T) {
    15  
    16  	type TestClrHeaders struct {
    17  		clrHeader            ImageCOR20Header
    18  		mdHeader             MetadataHeader
    19  		mdStreamHeaders      []MetadataStreamHeader
    20  		mdTablesStreamHeader MetadataTableStreamHeader
    21  	}
    22  
    23  	tests := []struct {
    24  		in  string
    25  		out TestClrHeaders
    26  	}{
    27  		{
    28  			getAbsoluteFilePath("test/mscorlib.dll"),
    29  			TestClrHeaders{
    30  				clrHeader: ImageCOR20Header{
    31  					Cb:                  0x48,
    32  					MajorRuntimeVersion: 0x2,
    33  					MinorRuntimeVersion: 0x5,
    34  					MetaData: ImageDataDirectory{
    35  						VirtualAddress: 0x2050,
    36  						Size:           0xae34,
    37  					},
    38  					Flags:                0x9,
    39  					EntryPointRVAorToken: 0x0,
    40  					StrongNameSignature: ImageDataDirectory{
    41  						VirtualAddress: 0xce84,
    42  						Size:           0x80,
    43  					},
    44  				},
    45  				mdHeader: MetadataHeader{
    46  					Signature:     0x424a5342,
    47  					MajorVersion:  0x1,
    48  					MinorVersion:  0x1,
    49  					ExtraData:     0x0,
    50  					VersionString: 0xc,
    51  					Version:       "v4.0.30319",
    52  					Flags:         0x0,
    53  					Streams:       0x5,
    54  				},
    55  				mdStreamHeaders: []MetadataStreamHeader{
    56  					{
    57  						Offset: 0x6c,
    58  						Size:   0x4c38,
    59  						Name:   "#~",
    60  					},
    61  					{
    62  						Offset: 0x4ca4,
    63  						Size:   0x5ed4,
    64  						Name:   "#Strings",
    65  					},
    66  					{
    67  						Offset: 0xab78,
    68  						Size:   0x4,
    69  						Name:   "#US",
    70  					},
    71  					{
    72  						Offset: 0xab7c,
    73  						Size:   0x10,
    74  						Name:   "#GUID",
    75  					},
    76  					{
    77  						Offset: 0xab8c,
    78  						Size:   0x2a8,
    79  						Name:   "#Blob",
    80  					},
    81  				},
    82  				mdTablesStreamHeader: MetadataTableStreamHeader{
    83  					Reserved:     0x0,
    84  					MajorVersion: 0x2,
    85  					MinorVersion: 0x0,
    86  					Heaps:        0x0,
    87  					RID:          0x1,
    88  					MaskValid:    0x8900005407,
    89  					Sorted:       0x16003301fa00,
    90  				},
    91  			},
    92  		},
    93  	}
    94  
    95  	for _, tt := range tests {
    96  		t.Run(tt.in, func(t *testing.T) {
    97  			ops := Options{Fast: true}
    98  			file, err := New(tt.in, &ops)
    99  			if err != nil {
   100  				t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
   101  			}
   102  
   103  			err = file.Parse()
   104  			if err != nil {
   105  				t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
   106  			}
   107  
   108  			var va, size uint32
   109  			switch file.Is64 {
   110  			case true:
   111  				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
   112  				dirEntry := oh64.DataDirectory[ImageDirectoryEntryCLR]
   113  				va = dirEntry.VirtualAddress
   114  				size = dirEntry.Size
   115  			case false:
   116  				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
   117  				dirEntry := oh32.DataDirectory[ImageDirectoryEntryCLR]
   118  				va = dirEntry.VirtualAddress
   119  				size = dirEntry.Size
   120  			}
   121  
   122  			err = file.parseCLRHeaderDirectory(va, size)
   123  			if err != nil {
   124  				t.Fatalf("parseCLRHeaderDirectory(%s) failed, reason: %v", tt.in, err)
   125  			}
   126  			clr := file.CLR
   127  			if clr.CLRHeader != tt.out.clrHeader {
   128  				t.Errorf("CLR header assertion failed, got %v, want %v",
   129  					clr.CLRHeader, tt.out.clrHeader)
   130  			}
   131  
   132  			if clr.MetadataHeader != tt.out.mdHeader {
   133  				t.Errorf("CLR metadata header assertion failed, got %v, want %v",
   134  					clr.MetadataHeader, tt.out.mdHeader)
   135  			}
   136  
   137  			if !reflect.DeepEqual(clr.MetadataStreamHeaders, tt.out.mdStreamHeaders) {
   138  				t.Errorf("CLR metadata stream headers assertion failed, got %v, want %v",
   139  					clr.MetadataStreamHeaders, tt.out.mdStreamHeaders)
   140  			}
   141  		})
   142  	}
   143  }
   144  
   145  func TestClrDirectoryMetadataTables(t *testing.T) {
   146  
   147  	type TestClrMetadataTable struct {
   148  		tableKind int
   149  		table     MetadataTable
   150  	}
   151  
   152  	tests := []struct {
   153  		in  string
   154  		out []TestClrMetadataTable
   155  	}{
   156  		{
   157  			getAbsoluteFilePath("test/mscorlib.dll"),
   158  			[]TestClrMetadataTable{
   159  				{
   160  					tableKind: Module,
   161  					table: MetadataTable{
   162  						Name:      "Module",
   163  						CountCols: 0x1,
   164  						Content: []ModuleTableRow{
   165  							{
   166  								Generation: 0x0,
   167  								Name:       0x2cd7,
   168  								Mvid:       0x1,
   169  								EncID:      0x0,
   170  								EncBaseID:  0x0,
   171  							},
   172  						},
   173  					},
   174  				},
   175  
   176  				{
   177  					tableKind: TypeRef,
   178  					table: MetadataTable{
   179  						Name:      "TypeRef",
   180  						CountCols: 19,
   181  						Content: []TypeRefTableRow{
   182  							{
   183  								ResolutionScope: 0x6,
   184  								TypeName:        0x22bd,
   185  								TypeNamespace:   0x4d80,
   186  							},
   187  						},
   188  					},
   189  				},
   190  
   191  				{
   192  					tableKind: MemberRef,
   193  					table: MetadataTable{
   194  						Name:      "MemberRef",
   195  						CountCols: 17,
   196  						Content: []MemberRefTableRow{
   197  							{
   198  								Class:     0x9,
   199  								Name:      0x4c76,
   200  								Signature: 0x1,
   201  							},
   202  						},
   203  					},
   204  				},
   205  
   206  				{
   207  					tableKind: CustomAttribute,
   208  					table: MetadataTable{
   209  						Name:      "CustomAttribute",
   210  						CountCols: 19,
   211  						Content: []CustomAttributeTableRow{
   212  							{
   213  								Parent: 0x27,
   214  								Type:   0x83,
   215  								Value:  0x2a1,
   216  							},
   217  						},
   218  					},
   219  				},
   220  
   221  				{
   222  					tableKind: DeclSecurity,
   223  					table: MetadataTable{
   224  						Name:      "DeclSecurity",
   225  						CountCols: 1,
   226  						Content: []DeclSecurityTableRow{
   227  							{
   228  								Action:        0x8,
   229  								Parent:        0x6,
   230  								PermissionSet: 0x52,
   231  							},
   232  						},
   233  					},
   234  				},
   235  
   236  				{
   237  					tableKind: Assembly,
   238  					table: MetadataTable{
   239  						Name:      "Assembly",
   240  						CountCols: 1,
   241  						Content: []AssemblyTableRow{
   242  							{
   243  								HashAlgId:      0x8004,
   244  								MajorVersion:   0x4,
   245  								MinorVersion:   0x0,
   246  								BuildNumber:    0x0,
   247  								RevisionNumber: 0x0,
   248  								Flags:          0x1,
   249  								PublicKey:      0x41,
   250  								Name:           0x704,
   251  								Culture:        0x0,
   252  							},
   253  						},
   254  					},
   255  				},
   256  
   257  				{
   258  					tableKind: AssemblyRef,
   259  					table: MetadataTable{
   260  						Name:      "AssemblyRef",
   261  						CountCols: 30,
   262  						Content: []AssemblyRefTableRow{
   263  							{
   264  								MajorVersion:     0x0,
   265  								MinorVersion:     0x0,
   266  								BuildNumber:      0x0,
   267  								RevisionNumber:   0x0,
   268  								Flags:            0x0,
   269  								PublicKeyOrToken: 0x26,
   270  								Name:             0x6ed,
   271  								Culture:          0x0,
   272  								HashValue:        0x0,
   273  							},
   274  						},
   275  					},
   276  				},
   277  
   278  				{
   279  					tableKind: ExportedType,
   280  					table: MetadataTable{
   281  						Name:      "ExportedType",
   282  						CountCols: 1319,
   283  						Content: []ExportedTypeTableRow{
   284  							{
   285  								Flags:          0x200000,
   286  								TypeDefId:      0x0,
   287  								TypeName:       0x5d85,
   288  								TypeNamespace:  0x316,
   289  								Implementation: 0x9,
   290  							},
   291  						},
   292  					},
   293  				},
   294  			},
   295  		},
   296  
   297  		{
   298  			getAbsoluteFilePath("test/pspluginwkr.dll"),
   299  			[]TestClrMetadataTable{
   300  				{
   301  					tableKind: Module,
   302  					table: MetadataTable{
   303  						Name:      "Module",
   304  						CountCols: 0x1,
   305  						Content: []ModuleTableRow{
   306  							{
   307  								Generation: 0x0,
   308  								Name:       0x8bdf,
   309  								Mvid:       0x1,
   310  								EncID:      0x0,
   311  								EncBaseID:  0x0,
   312  							},
   313  						},
   314  					},
   315  				},
   316  
   317  				{
   318  					tableKind: TypeRef,
   319  					table: MetadataTable{
   320  						Name:      "TypeRef",
   321  						CountCols: 140,
   322  						Content: []TypeRefTableRow{
   323  							{
   324  								ResolutionScope: 0x6,
   325  								TypeName:        0x1103,
   326  								TypeNamespace:   0x1113,
   327  							},
   328  						},
   329  					},
   330  				},
   331  
   332  				{
   333  					tableKind: TypeDef,
   334  					table: MetadataTable{
   335  						Name:      "TypeDef",
   336  						CountCols: 169,
   337  						Content: []TypeDefTableRow{
   338  							{
   339  								Flags:         0x0,
   340  								TypeName:      0x1,
   341  								TypeNamespace: 0x0,
   342  								Extends:       0x0,
   343  								FieldList:     0x1,
   344  								MethodList:    0x1,
   345  							},
   346  						},
   347  					},
   348  				},
   349  
   350  				{
   351  					tableKind: Field,
   352  					table: MetadataTable{
   353  						Name:      "Field",
   354  						CountCols: 325,
   355  						Content: []FieldTableRow{
   356  							{
   357  								Flags:     0x113,
   358  								Name:      0x4af1,
   359  								Signature: 0xea9,
   360  							},
   361  						},
   362  					},
   363  				},
   364  
   365  				{
   366  					tableKind: MethodDef,
   367  					table: MetadataTable{
   368  						Name:      "MethodDef",
   369  						CountCols: 434,
   370  						Content: []MethodDefTableRow{
   371  							{
   372  								RVA:       0x1d414,
   373  								ImplFlags: 0x0,
   374  								Flags:     0x13,
   375  								Name:      0x1b7f,
   376  								Signature: 0x125,
   377  								ParamList: 0x1,
   378  							},
   379  						},
   380  					},
   381  				},
   382  
   383  				{
   384  					tableKind: Param,
   385  					table: MetadataTable{
   386  						Name:      "Param",
   387  						CountCols: 679,
   388  						Content: []ParamTableRow{
   389  							{
   390  								Flags:    0x2000,
   391  								Sequence: 0x0,
   392  								Name:     0x0,
   393  							},
   394  						},
   395  					},
   396  				},
   397  
   398  				{
   399  					tableKind: InterfaceImpl,
   400  					table: MetadataTable{
   401  						Name:      "InterfaceImpl",
   402  						CountCols: 3,
   403  						Content: []InterfaceImplTableRow{
   404  							{
   405  								Class:     0x6c,
   406  								Interface: 0xa9,
   407  							},
   408  						},
   409  					},
   410  				},
   411  
   412  				{
   413  					tableKind: MemberRef,
   414  					table: MetadataTable{
   415  						Name:      "MemberRef",
   416  						CountCols: 256,
   417  						Content: []MemberRefTableRow{
   418  							{
   419  								Class:     0x29,
   420  								Name:      0x79f8,
   421  								Signature: 0x11e2,
   422  							},
   423  						},
   424  					},
   425  				},
   426  
   427  				{
   428  					tableKind: Constant,
   429  					table: MetadataTable{
   430  						Name:      "Constant",
   431  						CountCols: 2,
   432  						Content: []ConstantTableRow{
   433  							{
   434  								Type:   0xe,
   435  								Parent: 0x464,
   436  								Value:  0x1aa8,
   437  							},
   438  						},
   439  					},
   440  				},
   441  
   442  				{
   443  					tableKind: CustomAttribute,
   444  					table: MetadataTable{
   445  						Name:      "CustomAttribute",
   446  						CountCols: 622,
   447  						Content: []CustomAttributeTableRow{
   448  							{
   449  								Parent: 0x2e,
   450  								Type:   0x7db,
   451  								Value:  0x2c02,
   452  							},
   453  						},
   454  					},
   455  				},
   456  
   457  				{
   458  					tableKind: FieldMarshal,
   459  					table: MetadataTable{
   460  						Name:      "FieldMarshal",
   461  						CountCols: 33,
   462  						Content: []FieldMarshalTableRow{
   463  							{
   464  								Parent:     0x3,
   465  								NativeType: 0x1ca6,
   466  							},
   467  						},
   468  					},
   469  				},
   470  
   471  				{
   472  					tableKind: DeclSecurity,
   473  					table: MetadataTable{
   474  						Name:      "DeclSecurity",
   475  						CountCols: 4,
   476  						Content: []DeclSecurityTableRow{
   477  							{
   478  								Action:        0x8,
   479  								Parent:        0x6,
   480  								PermissionSet: 0x2d81,
   481  							},
   482  						},
   483  					},
   484  				},
   485  
   486  				{
   487  					tableKind: ClassLayout,
   488  					table: MetadataTable{
   489  						Name:      "ClassLayout",
   490  						CountCols: 144,
   491  						Content: []ClassLayoutTableRow{
   492  							{
   493  								PackingSize: 0x0,
   494  								ClassSize:   0x10,
   495  								Parent:      0x2,
   496  							},
   497  						},
   498  					},
   499  				},
   500  
   501  				{
   502  					tableKind: StandAloneSig,
   503  					table: MetadataTable{
   504  						Name:      "StandAloneSig",
   505  						CountCols: 358,
   506  						Content: []StandAloneSigTableRow{
   507  							{
   508  								Signature: 0x1caa,
   509  							},
   510  						},
   511  					},
   512  				},
   513  
   514  				{
   515  					tableKind: EventMap,
   516  					table: MetadataTable{
   517  						Name:      "EventMap",
   518  						CountCols: 2,
   519  						Content: []EventMapTableRow{
   520  							{
   521  								Parent:    0x7f,
   522  								EventList: 0x1,
   523  							},
   524  						},
   525  					},
   526  				},
   527  
   528  				{
   529  					tableKind: Event,
   530  					table: MetadataTable{
   531  						Name:      "Event",
   532  						CountCols: 2,
   533  						Content: []EventTableRow{
   534  							{
   535  								EventFlags: 0x200,
   536  								Name:       0x7eeb,
   537  								EventType:  0x16,
   538  							},
   539  						},
   540  					},
   541  				},
   542  
   543  				{
   544  					tableKind: PropertyMap,
   545  					table: MetadataTable{
   546  						Name:      "PropertyMap",
   547  						CountCols: 2,
   548  						Content: []PropertyMapTableRow{
   549  							{
   550  								Parent:       0x49,
   551  								PropertyList: 0x1,
   552  							},
   553  						},
   554  					},
   555  				},
   556  
   557  				{
   558  					tableKind: Property,
   559  					table: MetadataTable{
   560  						Name:      "Property",
   561  						CountCols: 2,
   562  						Content: []PropertyTableRow{
   563  							{
   564  								Flags: 0x0,
   565  								Name:  0x7a8a,
   566  								Type:  0x11d7,
   567  							},
   568  						},
   569  					},
   570  				},
   571  
   572  				{
   573  					tableKind: MethodSemantics,
   574  					table: MetadataTable{
   575  						Name:      "MethodSemantics",
   576  						CountCols: 9,
   577  						Content: []MethodSemanticsTableRow{
   578  							{
   579  								Semantics:   0x10,
   580  								Method:      0x153,
   581  								Association: 0x2,
   582  							},
   583  						},
   584  					},
   585  				},
   586  
   587  				{
   588  					tableKind: ModuleRef,
   589  					table: MetadataTable{
   590  						Name:      "ModuleRef",
   591  						CountCols: 1,
   592  						Content: []ModuleRefTableRow{
   593  							{
   594  								Name: 0x0,
   595  							},
   596  						},
   597  					},
   598  				},
   599  
   600  				{
   601  					tableKind: TypeSpec,
   602  					table: MetadataTable{
   603  						Name:      "TypeSpec",
   604  						CountCols: 17,
   605  						Content: []TypeSpecTableRow{
   606  							{
   607  								Signature: 0x85,
   608  							},
   609  						},
   610  					},
   611  				},
   612  
   613  				{
   614  					tableKind: ImplMap,
   615  					table: MetadataTable{
   616  						Name:      "ImplMap",
   617  						CountCols: 51,
   618  						Content: []ImplMapTableRow{
   619  							{
   620  								MappingFlags:    0x240,
   621  								MemberForwarded: 0x1cb,
   622  								ImportName:      0x0,
   623  								ImportScope:     0x1,
   624  							},
   625  						},
   626  					},
   627  				},
   628  
   629  				{
   630  					tableKind: FieldRVA,
   631  					table: MetadataTable{
   632  						Name:      "FieldRVA",
   633  						CountCols: 265,
   634  						Content: []FieldRVATableRow{
   635  							{
   636  								RVA:   0x11e4,
   637  								Field: 0x1,
   638  							},
   639  						},
   640  					},
   641  				},
   642  
   643  				{
   644  					tableKind: Assembly,
   645  					table: MetadataTable{
   646  						Name:      "Assembly",
   647  						CountCols: 1,
   648  						Content: []AssemblyTableRow{
   649  							{
   650  								HashAlgId:      0x8004,
   651  								MajorVersion:   0x1,
   652  								MinorVersion:   0x0,
   653  								BuildNumber:    0x0,
   654  								RevisionNumber: 0x0,
   655  								Flags:          0x1,
   656  								PublicKey:      0x2b03,
   657  								Name:           0x8bd3,
   658  								Culture:        0x0,
   659  							},
   660  						},
   661  					},
   662  				},
   663  
   664  				{
   665  					tableKind: AssemblyRef,
   666  					table: MetadataTable{
   667  						Name:      "AssemblyRef",
   668  						CountCols: 5,
   669  						Content: []AssemblyRefTableRow{
   670  							{
   671  								MajorVersion:     0x2,
   672  								MinorVersion:     0x0,
   673  								BuildNumber:      0x0,
   674  								RevisionNumber:   0x0,
   675  								Flags:            0x0,
   676  								PublicKeyOrToken: 0x1,
   677  								Name:             0x10b9,
   678  								Culture:          0x0,
   679  								HashValue:        0xa,
   680  							},
   681  						},
   682  					},
   683  				},
   684  
   685  				{
   686  					tableKind: NestedClass,
   687  					table: MetadataTable{
   688  						Name:      "NestedClass",
   689  						CountCols: 7,
   690  						Content: []NestedClassTableRow{
   691  							{
   692  								NestedClass:    0x7,
   693  								EnclosingClass: 0x6,
   694  							},
   695  						},
   696  					},
   697  				},
   698  			},
   699  		},
   700  	}
   701  
   702  	for _, tt := range tests {
   703  		t.Run(tt.in, func(t *testing.T) {
   704  			ops := Options{Fast: true}
   705  			file, err := New(tt.in, &ops)
   706  			if err != nil {
   707  				t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
   708  			}
   709  
   710  			err = file.Parse()
   711  			if err != nil {
   712  				t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
   713  			}
   714  
   715  			var va, size uint32
   716  			switch file.Is64 {
   717  			case true:
   718  				oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
   719  				dirEntry := oh64.DataDirectory[ImageDirectoryEntryCLR]
   720  				va = dirEntry.VirtualAddress
   721  				size = dirEntry.Size
   722  			case false:
   723  				oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
   724  				dirEntry := oh32.DataDirectory[ImageDirectoryEntryCLR]
   725  				va = dirEntry.VirtualAddress
   726  				size = dirEntry.Size
   727  			}
   728  
   729  			err = file.parseCLRHeaderDirectory(va, size)
   730  			if err != nil {
   731  				t.Fatalf("parseCLRHeaderDirectory(%s) failed, reason: %v", tt.in, err)
   732  			}
   733  
   734  			clr := file.CLR
   735  			for _, tbl := range tt.out {
   736  				mdTable := clr.MetadataTables[tbl.tableKind]
   737  				if mdTable.CountCols != tbl.table.CountCols {
   738  					t.Errorf("CLR metadata tables assertion failed on %s table, got %v, want %v",
   739  						tbl.table.Name, mdTable.CountCols, tbl.table.CountCols)
   740  				}
   741  				if mdTable.Name != tbl.table.Name {
   742  					t.Errorf("CLR metadata tables assertion failed on %s table, got %v, want %v",
   743  						tbl.table.Name, mdTable.Name, tbl.table)
   744  				}
   745  
   746  				var got, want interface{}
   747  				switch mdTable.Content.(type) {
   748  				case []ModuleTableRow:
   749  					got = mdTable.Content.([]ModuleTableRow)[0]
   750  					want = tbl.table.Content.([]ModuleTableRow)[0]
   751  				case []TypeRefTableRow:
   752  					got = mdTable.Content.([]TypeRefTableRow)[0]
   753  					want = tbl.table.Content.([]TypeRefTableRow)[0]
   754  				case []TypeDefTableRow:
   755  					got = mdTable.Content.([]TypeDefTableRow)[0]
   756  					want = tbl.table.Content.([]TypeDefTableRow)[0]
   757  				case []MemberRefTableRow:
   758  					got = mdTable.Content.([]MemberRefTableRow)[0]
   759  					want = tbl.table.Content.([]MemberRefTableRow)[0]
   760  				case []CustomAttributeTableRow:
   761  					got = mdTable.Content.([]CustomAttributeTableRow)[0]
   762  					want = tbl.table.Content.([]CustomAttributeTableRow)[0]
   763  				case []DeclSecurityTableRow:
   764  					got = mdTable.Content.([]DeclSecurityTableRow)[0]
   765  					want = tbl.table.Content.([]DeclSecurityTableRow)[0]
   766  				case []AssemblyTableRow:
   767  					got = mdTable.Content.([]AssemblyTableRow)[0]
   768  					want = tbl.table.Content.([]AssemblyTableRow)[0]
   769  				case []AssemblyRefTableRow:
   770  					got = mdTable.Content.([]AssemblyRefTableRow)[0]
   771  					want = tbl.table.Content.([]AssemblyRefTableRow)[0]
   772  				case []ExportedTypeTableRow:
   773  					got = mdTable.Content.([]ExportedTypeTableRow)[0]
   774  					want = tbl.table.Content.([]ExportedTypeTableRow)[0]
   775  				case []FieldTableRow:
   776  					got = mdTable.Content.([]FieldTableRow)[0]
   777  					want = tbl.table.Content.([]FieldTableRow)[0]
   778  				case []MethodDefTableRow:
   779  					got = mdTable.Content.([]MethodDefTableRow)[0]
   780  					want = tbl.table.Content.([]MethodDefTableRow)[0]
   781  				case []ParamTableRow:
   782  					got = mdTable.Content.([]ParamTableRow)[0]
   783  					want = tbl.table.Content.([]ParamTableRow)[0]
   784  				case []InterfaceImplTableRow:
   785  					got = mdTable.Content.([]InterfaceImplTableRow)[0]
   786  					want = tbl.table.Content.([]InterfaceImplTableRow)[0]
   787  				case []ConstantTableRow:
   788  					got = mdTable.Content.([]ConstantTableRow)[0]
   789  					want = tbl.table.Content.([]ConstantTableRow)[0]
   790  				case []FieldMarshalTableRow:
   791  					got = mdTable.Content.([]FieldMarshalTableRow)[0]
   792  					want = tbl.table.Content.([]FieldMarshalTableRow)[0]
   793  				case []ClassLayoutTableRow:
   794  					got = mdTable.Content.([]ClassLayoutTableRow)[0]
   795  					want = tbl.table.Content.([]ClassLayoutTableRow)[0]
   796  				case []StandAloneSigTableRow:
   797  					got = mdTable.Content.([]StandAloneSigTableRow)[0]
   798  					want = tbl.table.Content.([]StandAloneSigTableRow)[0]
   799  				case []EventMapTableRow:
   800  					got = mdTable.Content.([]EventMapTableRow)[0]
   801  					want = tbl.table.Content.([]EventMapTableRow)[0]
   802  				case []EventTableRow:
   803  					got = mdTable.Content.([]EventTableRow)[0]
   804  					want = tbl.table.Content.([]EventTableRow)[0]
   805  				case []PropertyMapTableRow:
   806  					got = mdTable.Content.([]PropertyMapTableRow)[0]
   807  					want = tbl.table.Content.([]PropertyMapTableRow)[0]
   808  				case []PropertyTableRow:
   809  					got = mdTable.Content.([]PropertyTableRow)[0]
   810  					want = tbl.table.Content.([]PropertyTableRow)[0]
   811  				case []MethodSemanticsTableRow:
   812  					got = mdTable.Content.([]MethodSemanticsTableRow)[0]
   813  					want = tbl.table.Content.([]MethodSemanticsTableRow)[0]
   814  				case []ModuleRefTableRow:
   815  					got = mdTable.Content.([]ModuleRefTableRow)[0]
   816  					want = tbl.table.Content.([]ModuleRefTableRow)[0]
   817  				case []TypeSpecTableRow:
   818  					got = mdTable.Content.([]TypeSpecTableRow)[0]
   819  					want = tbl.table.Content.([]TypeSpecTableRow)[0]
   820  				case []ImplMapTableRow:
   821  					got = mdTable.Content.([]ImplMapTableRow)[0]
   822  					want = tbl.table.Content.([]ImplMapTableRow)[0]
   823  				case []FieldRVATableRow:
   824  					got = mdTable.Content.([]FieldRVATableRow)[0]
   825  					want = tbl.table.Content.([]FieldRVATableRow)[0]
   826  				case []NestedClassTableRow:
   827  					got = mdTable.Content.([]NestedClassTableRow)[0]
   828  					want = tbl.table.Content.([]NestedClassTableRow)[0]
   829  				default:
   830  					got = "bad type"
   831  					want = "good type"
   832  				}
   833  				if !reflect.DeepEqual(got, want) {
   834  					t.Errorf("CLR metadata tables assertion failed on %s table, got %v, want %v",
   835  						tbl.table.Name, got, want)
   836  				}
   837  
   838  			}
   839  		})
   840  	}
   841  }
   842  
   843  func TestClrDirectorCOMImageFlagsType(t *testing.T) {
   844  
   845  	tests := []struct {
   846  		in  int
   847  		out []string
   848  	}{
   849  		{
   850  			0x9,
   851  			[]string{"IL Only", "Strong Name Signed"},
   852  		},
   853  	}
   854  
   855  	for _, tt := range tests {
   856  		t.Run("CaseFlagsEqualTo_"+strconv.Itoa(tt.in), func(t *testing.T) {
   857  			got := COMImageFlagsType(tt.in).String()
   858  			sort.Strings(got)
   859  			sort.Strings(tt.out)
   860  			if !reflect.DeepEqual(got, tt.out) {
   861  				t.Errorf("CLR header flags assertion failed, got %v, want %v",
   862  					got, tt.out)
   863  			}
   864  		})
   865  	}
   866  }