예제 #1
0
func check(i interface{}, name content.FullyQualifiedName) error {
	if err := content.Validate(i); err != nil {
		return err
	}
	if name.Relative[0] == '<' || name.Relative[0] == '$' {
		return errors.New(fmt.Sprintf("Not .net referenceable name: %s", name))
	}
	return nil
}
func TestLoadAllAssemblies(t *testing.T) {
	paths := DefaultPaths()
	if len(paths) == 0 {
		t.Skip("Neither mono nor Windows .NET Framework paths were possible to get")
	}
	var (
		inChan  = make(chan string, 64)
		outChan = make(chan error, 32)
		wg      sync.WaitGroup
		once    sync.Once
	)
	worker := func() {
		wg.Add(1)

		for fn := range inChan {
			start := time.Now()
			data, err := ioutil.ReadFile(fn)
			if err != nil {
				outChan <- errors.New(fmt.Sprintf("%s: %s\n", fn, err))
				continue
			}
			if asm, err := LoadAssembly(bytes.NewReader(data)); err != nil {
				if err != ErrNotAssembly && err != ErrMetadata {
					outChan <- errors.New(fmt.Sprintf("%s: %s\n", fn, err))
				} else {
					t.Logf("%s is not a .net assembly", fn)
				}
			} else {
				ci := ConcreteTableIndex{metadataUtil: &asm.MetadataUtil, table: id_TypeDef, index: 1}
				for i := uint32(0); i < asm.Tables[id_TypeDef].Rows; i++ {
					ci.index = i + 1
					if td, err := TypeDefFromIndex(&ci); err != nil {
						outChan <- errors.New(fmt.Sprintf("%s: %s\n", fn, err))
					} else {
						if n := td.Name(); content.Validate(&n) != nil {
							continue
						} else if _, err := td.ToContentType(); err != nil {
							outChan <- errors.New(fmt.Sprintf("%s: %s\n", fn, err))
						}
					}
				}
				ci.table = id_Module
				ci.index = 1
				if d, err := ci.Data(); err != nil {
					outChan <- errors.New(fmt.Sprintf("%s: %s\n", fn, err))
				} else {
					mr := d.(*ModuleRow)
					ci.table = id_Assembly
					if d2, err := ci.Data(); err != nil {
						if asm.Tables[id_Assembly].Rows == 0 {
							// It's ok for an assembly to not have an assembly table, although
							// I've only ever seen this with System.EnterpriseServices.Wrapper.dll
							t.Logf("Successfully loaded module %50s {%s}", mr.Name, mr.Mvid)
						} else {
							outChan <- errors.New(fmt.Sprintf("%s: %s\n", fn, err))
						}
					} else {
						ar := d2.(*AssemblyRow)
						if mn, an := string(mr.Name), string(ar.Name); !strings.HasPrefix(mn, an) && (an != "mscorlib" && mn != "CommonLanguageRuntimeLibrary") {
							outChan <- errors.New(fmt.Sprintf("The assembly name isn't the prefix of the module name: %s, %s", an, mn))
						} else {
							t.Logf("Successfully loaded module %50s {%s} %s (%s)", mn, mr.Mvid, an, time.Now().Sub(start))
						}
					}
				}
			}
		}
		wg.Done()
		wg.Wait()
		once.Do(func() {
			close(outChan)
		})
	}
	for i := 0; i < runtime.NumCPU(); i++ {
		go worker()
	}

	for _, path := range paths {
		if f, err := os.Open(path); err != nil {
			t.Error(err)
		} else {
			fi, err := f.Readdir(0)
			if err != nil {
				t.Fatal(err)
			}

			for i := 0; i < len(fi); {
				if fn := fi[i].Name(); strings.HasSuffix(fn, ".dll") {
					if len(inChan)+1 >= cap(inChan) {
						for len(outChan) > 0 {
							o := <-outChan
							if o != nil {
								t.Error(o)
							}
						}
						time.Sleep(time.Microsecond * 100)
					} else {
						inChan <- path + fn
						i++
					}
				} else {
					i++
				}
			}
		}
	}
	close(inChan)
	for o := range outChan {
		if o != nil {
			t.Error(o)
		}
	}
}
예제 #3
0
func (td *TypeDef) ToContentType() (t *content.Type, err error) {
	if td.ct.Name.Relative != "" {
		return &td.ct, nil
	}
	t = &content.Type{}
	t.Name = td.Name()
	t.Flags = td.row.Flags.Convert()

	if ext, err := td.Extends(); err != nil && err != ErrInterface {
		return nil, err
	} else {
		t.Extends = ext
	}
	if imp, err := td.Implements(); err != nil {
		return nil, err
	} else {
		t.Implements = imp
	}
	if f, err := td.Fields(); err != nil {
		return nil, err
	} else {
		t.Fields = f
	}
	if f, err := td.Methods(); err != nil {
		return nil, err
	} else {
		t.Methods = f
	}

	idx := td.mu.Search(id_NestedClass, func(ti TableIndex) bool {
		if raw, err := ti.Data(); err == nil {
			c := raw.(*NestedClassRow)
			return c.NestedClass.Index() > td.index.Index()
		}
		return false
	})
	if idx != nil {
		ci := idx.(*ConcreteTableIndex)
		table := td.mu.Tables[idx.Table()]
		for i := idx.Index(); i < table.Rows+1; i++ {
			ci.index = i
			if raw, err := ci.Data(); err != nil {
				return nil, err
			} else {
				row := raw.(*NestedClassRow)
				if row.EnclosingClass.Index() != td.index.Index() {
					break
				} else if td2, err := TypeDefFromIndex(row.NestedClass); err != nil {
					return nil, err
				} else {
					ct := content.Type{}
					ct.Name = td2.Name()
					ct.Flags = td2.row.Flags.Convert()
					if err := check(&ct, ct.Name); err != nil {
						log4go.Fine("Skipping nested type: %s, %+v, %+v", err, ct, td2.row)
						continue
					}

					t.Types = append(t.Types, ct)
				}
			}
		}
	}
	err = content.Validate(&t)
	td.ct = *t
	return
}