target/armv7m,cortex_m: introduce checked arch_info cast routines
[fw/openocd] / src / target / cortex_m.h
index cabe405ce1c99b3a6b771b26048937514c85bc6d..8fb34f46c12fa2ce49b4aeb4cf98c370f8a2461d 100644 (file)
@@ -247,13 +247,6 @@ struct cortex_m_common {
        bool maskints_erratum;
 };
 
-static inline struct cortex_m_common *
-target_to_cm(struct target *target)
-{
-       return container_of(target->arch_info,
-                       struct cortex_m_common, armv7m.arm);
-}
-
 static inline bool is_cortex_m_or_hla(const struct cortex_m_common *cortex_m)
 {
        return cortex_m->common_magic == CORTEX_M_COMMON_MAGIC;
@@ -267,6 +260,40 @@ static inline bool is_cortex_m_with_dap_access(const struct cortex_m_common *cor
        return !cortex_m->armv7m.is_hla_target;
 }
 
+/**
+ * @returns the pointer to the target specific struct
+ * without matching a magic number.
+ * Use in target specific service routines, where the correct
+ * type of arch_info is certain.
+ */
+static inline struct cortex_m_common *
+target_to_cm(struct target *target)
+{
+       return container_of(target->arch_info,
+                       struct cortex_m_common, armv7m.arm);
+}
+
+/**
+ * @returns the pointer to the target specific struct
+ * or NULL if the magic number does not match.
+ * Use in a flash driver or any place where mismatch of the arch_info
+ * type can happen.
+ */
+static inline struct cortex_m_common *
+target_to_cortex_m_safe(struct target *target)
+{
+       /* Check the parent types first to prevent peeking memory too far
+        * from arch_info pointer */
+       if (!target_to_armv7m_safe(target))
+               return NULL;
+
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       if (!is_cortex_m_or_hla(cortex_m))
+               return NULL;
+
+       return cortex_m;
+}
+
 int cortex_m_examine(struct target *target);
 int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint);
 int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoint);