diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,13 @@
+# Revision history for distribution-nixpkgs
+
+## 1.6.0
+
+* `Distribution.Nixpkgs.PackageMap`
+  * `readNixpkgPackageMap`: instead of a list of arguments to pass to
+    `nix-env`, take path to nixpkgs and an optional nix expression
+    to pass to it as arguments.
+  * `readNixpkgPackageMap`: populate `PackageMap` with *all* attribute
+    paths that point to derivations instead of just one per derivation.
+    This fixes `resolve` not finding certain identifiers if there were
+    two attributes pointing to the same derivation in nixpkgs. See also
+    [#9](https://github.com/NixOS/distribution-nixpkgs/issues/9).
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+# distribution-nixpkgs
+
+[![hackage release](https://img.shields.io/hackage/v/distribution-nixpkgs.svg?label=hackage)](http://hackage.haskell.org/package/distribution-nixpkgs)
+[![stackage LTS package](http://stackage.org/package/distribution-nixpkgs/badge/lts)](http://stackage.org/lts/package/distribution-nixpkgs)
diff --git a/derivation-attr-paths.nix b/derivation-attr-paths.nix
new file mode 100644
--- /dev/null
+++ b/derivation-attr-paths.nix
@@ -0,0 +1,42 @@
+{ nixpkgsPath ? <nixpkgs>
+, nixpkgsArgs ? {}
+}@args:
+
+let
+  pkgs = import nixpkgsPath nixpkgsArgs;
+
+  inherit (pkgs) lib;
+
+  /* Condition for us to recurse:
+     Either we are at the top-level or
+     recurseForDerivations is true.
+
+     Type :: list any -> any -> bool
+  */
+  recurseInto = path: x: path == [] ||
+    (lib.isAttrs x && (x.recurseForDerivations or false));
+
+  /* Takes the nixpkgs set and returns all attribute paths
+     to reachable derivations within it as a list of lists of
+     strings.
+
+     Type :: attrs -> list (list string)
+  */
+  derivationPaths =
+    let
+      go = path: x:
+        let
+          inherit (builtins.tryEval x)
+            value
+            success
+            ;
+        in
+          if !success then []
+          else if lib.isDerivation value then [
+            path
+          ] else if recurseInto path x then lib.concatLists (
+            lib.mapAttrsToList (n: go (path ++ [ n ])) x
+          ) else [];
+    in go [];
+in
+  derivationPaths pkgs
diff --git a/distribution-nixpkgs.cabal b/distribution-nixpkgs.cabal
--- a/distribution-nixpkgs.cabal
+++ b/distribution-nixpkgs.cabal
@@ -1,20 +1,23 @@
 name:          distribution-nixpkgs
-version:       1.5.0
+version:       1.6.0
 synopsis:      Types and functions to manipulate the Nixpkgs distribution
 description:   Types and functions to represent, query, and manipulate the Nixpkgs distribution.
 license:       BSD3
 license-file:  LICENSE
 maintainer:    Peter Simons <simons@cryp.to>
-tested-with:   GHC == 8.0.2 || == 8.2.2 || == 8.4.4 || == 8.6.5 || == 8.8.4 || == 8.10.4
+tested-with:   GHC == 8.6.5 || == 8.8.4 || == 8.10.4 || == 9.0.1
 category:      Distribution, Nix
-homepage:      https://github.com/peti/distribution-nixpkgs
-bug-reports:   https://github.com/peti/distribution-nixpkgs/issues
+homepage:      https://github.com/NixOS/distribution-nixpkgs
+bug-reports:   https://github.com/NixOS/distribution-nixpkgs/issues
 build-type:    Simple
 cabal-version: >= 1.10
+data-files:    derivation-attr-paths.nix
+extra-source-files: CHANGELOG.md
+                    README.md
 
 source-repository head
   type:     git
-  location: https://github.com/peti/distribution-nixpkgs
+  location: https://github.com/NixOS/distribution-nixpkgs
 
 library
   exposed-modules:    Distribution.Nixpkgs.Hashes
@@ -22,6 +25,7 @@
                       Distribution.Nixpkgs.Meta
                       Distribution.Nixpkgs.PackageMap
                       Language.Nix.PrettyPrinting
+  other-modules:      Paths_distribution_nixpkgs
   hs-source-dirs:     src
   build-depends:      base         > 4.2 && < 5
                     , Cabal        >= 2.4
@@ -35,7 +39,6 @@
                     , process
                     , split
   default-language:   Haskell2010
-  default-extensions: MonadFailDesugaring
   other-extensions:   CPP
                       TemplateHaskell
                       RecordWildCards
diff --git a/src/Distribution/Nixpkgs/License.hs b/src/Distribution/Nixpkgs/License.hs
--- a/src/Distribution/Nixpkgs/License.hs
+++ b/src/Distribution/Nixpkgs/License.hs
@@ -2,8 +2,8 @@
 
 {- |
    Known licenses in Nix expressions are represented using the
-   attributes defined in @pkgs\/lib\/licenses.nix@, and unknown licenses
-   are represented as a literal string.
+   attributes defined in nixpkgs' @lib\/licenses.nix@, and
+   unknown licenses are represented as a literal string.
  -}
 
 module Distribution.Nixpkgs.License ( License(..) ) where
@@ -14,27 +14,28 @@
 import Language.Nix.PrettyPrinting
 
 -- | The representation for licenses used in Nix derivations. Known
--- licenses are Nix expressions -- such as @lib.licenses.bsd3@
--- --, so their exact \"name\" is not generally known, because the path
--- to @lib@ depends on the context defined in the expression. In
--- Cabal expressions, for example, the BSD3 license would have to be
+-- licenses are Nix expressions — such as @lib.licenses.bsd3@ —,
+-- so their exact name is not generally known, because the path
+-- to @lib@ depends on the context defined in the expression.
+--
+-- In Cabal expressions, for example, the BSD3 license would have to be
 -- referred to as @self.lib.licenses.bsd3@. Other expressions,
--- however, use different paths to the @licenses@ record. Because of tat
+-- however, use different paths to the @licenses@ record. Because of that
 -- situation, the library cannot provide an abstract data type that
--- encompasses all known licenses. Instead, the @License@ type just
--- distinguishes references to known and unknown licenses. The
--- difference between the two is in the way they are pretty-printed:
+-- encompasses all known licenses.
 --
--- > > putStrLn (display (Known "lib.license.gpl2"))
--- > lib.license.gpl2
--- >
--- > > putStrLn (display (Unknown (Just "GPL")))
--- > "GPL"
--- >
--- > > putStrLn (display (Unknown Nothing))
--- > "unknown"
+-- Instead, the @License@ type just distinguishes references to known
+-- and unknown licenses. The difference between the two is in the way
+-- they are pretty-printed:
 --
--- Note that the "Text" instance definition provides pretty-printing,
+-- >>> putStrLn (prettyShow (Known "lib.license.gpl2"))
+-- lib.license.gpl2
+-- >>> putStrLn (prettyShow (Unknown (Just "GPL")))
+-- "GPL"
+-- >>> putStrLn (prettyShow (Unknown Nothing))
+-- "unknown"
+--
+-- Note that the 'Pretty' instance definition provides pretty-printing,
 -- but no parsing as of now!
 
 data License = Known String
diff --git a/src/Distribution/Nixpkgs/Meta.hs b/src/Distribution/Nixpkgs/Meta.hs
--- a/src/Distribution/Nixpkgs/Meta.hs
+++ b/src/Distribution/Nixpkgs/Meta.hs
@@ -76,10 +76,7 @@
 renderPlatforms :: String -> Set Platform -> Doc
 renderPlatforms field ps
   | Set.null ps = sep [ text field <+> equals <+> text "lib.platforms.none" <> semi ]
-  | otherwise   = sep [ text field <+> equals <+> lbrack
-                      , nest 2 $ fsep $ map text (toAscList (Set.map fromCabalPlatform ps))
-                      , rbrack <> semi
-                      ]
+  | otherwise   = setattr field mempty $ Set.map fromCabalPlatform ps
 
 nullMeta :: Meta
 nullMeta = Meta
diff --git a/src/Distribution/Nixpkgs/PackageMap.hs b/src/Distribution/Nixpkgs/PackageMap.hs
--- a/src/Distribution/Nixpkgs/PackageMap.hs
+++ b/src/Distribution/Nixpkgs/PackageMap.hs
@@ -1,3 +1,4 @@
+-- | Build a lookup table from package identifiers to full attribute paths in nixpkgs.
 module Distribution.Nixpkgs.PackageMap
   ( PackageMap, readNixpkgPackageMap
   , resolve
@@ -7,45 +8,78 @@
 import qualified Data.Aeson as JSON
 import qualified Data.ByteString.Lazy as LBS
 import Data.Function
-import Data.List as List
-import Data.List.Split
+import Data.List (minimumBy)
 import Data.Map.Strict ( Map )
 import qualified Data.Map.Strict as Map
 import Data.Maybe
 import Data.Set ( Set )
 import qualified Data.Set as Set
 import Language.Nix
+import Paths_distribution_nixpkgs (getDataFileName)
 import System.Process
 
 type PackageMap = Map Identifier (Set Path)
 
-readNixpkgPackageMap :: [String] -> IO PackageMap
-readNixpkgPackageMap = fmap identifierSet2PackageMap . readNixpkgSet
+-- | Evaluate nixpkgs at a given (nix) path and build a 'Map'
+--   keeping track of all 'Path's that end in a given 'Identifier'
+--   and evaluate to a derivation.
+--   This can be used to find an attribute 'Path' for an arbitrary
+--   package name using 'resolve'.
+--
+--   Note: Evaluation of nixpkgs is very expensive (takes multiple
+--   seconds), so cache the result of this function if possible.
+--
+--   >>> readNixpkgPackageMap "<nixpkgs>" (Just "{ config = { allowAliases = false; }; }")
+--   fromList [ … ]
+readNixpkgPackageMap :: String
+                     -- ^ Path to nixpkgs, must be a valid nix path
+                     --   (absolute, relative or @NIX_PATH@ lookup)
+                     -> Maybe String
+                     -- ^ (Optional) argument attribute set to pass to
+                     --   nixpkgs. Must be a valid nix attribute set.
+                     -> IO PackageMap
+readNixpkgPackageMap nixpkgsPath nixpkgsArgs =
+  identifierSet2PackageMap <$> readNixpkgSet nixpkgsPath nixpkgsArgs
 
-readNixpkgSet :: [String] -> IO (Set String)
-readNixpkgSet extraArgs = do
-  (_, Just h, _, _) <- createProcess (proc "nix-env" (["-qaP", "--json"] ++ extraArgs))
-                       { std_out = CreatePipe, env = Nothing }  -- TODO: ensure that overrides don't screw up our results
+readNixpkgSet :: String -> Maybe String -> IO (Set [String])
+readNixpkgSet nixpkgsPath nixpkgsArgs = do
+  pathsExpr <- getDataFileName "derivation-attr-paths.nix"
+  let nixInstantiate = proc "nix-instantiate"
+        [ "--strict"
+        , "--json"
+        , "--eval"
+        , pathsExpr
+        , "--arg", "nixpkgsPath", nixpkgsPath
+        , "--arg", "nixpkgsArgs", fromMaybe "{}" nixpkgsArgs
+        ]
+  (_, Just h, _, _) <- -- TODO: ensure that overrides don't screw up our results
+    createProcess nixInstantiate { std_out = CreatePipe, env = Nothing }
   buf <- LBS.hGetContents h
-  let pkgmap :: Either String (Map String JSON.Object)
-      pkgmap = JSON.eitherDecode buf
-  either fail (return . Map.keysSet) pkgmap
+  either fail return $ JSON.eitherDecode buf
 
-identifierSet2PackageMap :: Set String -> PackageMap
-identifierSet2PackageMap pkgset = foldr (uncurry insertIdentifier) Map.empty pkglist
+identifierSet2PackageMap :: Set [String] -> PackageMap
+identifierSet2PackageMap = foldr insertIdentifier Map.empty
   where
-    pkglist :: [(Identifier, Path)]
-    pkglist = mapMaybe parsePackage (Set.toList pkgset)
-
-    insertIdentifier :: Identifier -> Path -> PackageMap -> PackageMap
-    insertIdentifier i = Map.insertWith Set.union i . Set.singleton
+    insertIdentifier :: [String] -> (PackageMap -> PackageMap)
+    insertIdentifier rawPath =
+      case parsePackage rawPath of
+        Nothing -> id
+        Just (i, p) -> Map.insertWith Set.union i $ Set.singleton p
 
-parsePackage :: String -> Maybe (Identifier, Path)
-parsePackage x | null x                 = error "Distribution.Nixpkgs.PackageMap.parsepackage: empty string is no valid identifier"
-               | xs <- splitOn "." x    = if needsQuoting (head xs)
-                                             then Nothing
-                                             else Just (ident # last xs, path # map (review ident) xs)
+parsePackage :: [String] -> Maybe (Identifier, Path)
+parsePackage x
+  | null x = -- this case would be a bug in derivation-attr-paths.nix
+      error "Distribution.Nixpkgs.PackageMap.parsepackage: empty path is no valid identifier"
+  | otherwise =
+      if any needsQuoting x
+        then Nothing
+        else Just (ident # last x, path # map (review ident) x)
 
+-- | Finds the shortest 'Path' in a 'PackageMap' that has the
+--   given 'Identifier' as its last component.
+--
+--   >>> resolve nixpkgs (ident # "pam")
+--   Just (Bind (Identifier "pam") (Path [Identifier "pam"]))
 resolve :: PackageMap -> Identifier -> Maybe Binding
 resolve nixpkgs i = case Map.lookup i nixpkgs of
                       Nothing -> Nothing
diff --git a/src/Language/Nix/PrettyPrinting.hs b/src/Language/Nix/PrettyPrinting.hs
--- a/src/Language/Nix/PrettyPrinting.hs
+++ b/src/Language/Nix/PrettyPrinting.hs
@@ -22,7 +22,7 @@
 #endif
 import Data.Char
 import Data.Function
-import Data.List
+import Data.List (sortBy)
 import Data.Set ( Set )
 import qualified Data.Set as Set
 import "pretty" Text.PrettyPrint.HughesPJClass
